如何在Xaml中使用折叠控件调整UI

本文关键字:折叠 控件 调整 UI Xaml | 更新日期: 2023-09-27 18:08:25

我的项目适用于WP8.1,我使用的是Silverlight。在这个项目中,我有两个矩形,一个蓝色的和一个红色的。我想每个都占屏幕宽度的50%,所以我做了这个:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Rectangle Grid.Column="0" Fill="Blue" Visibility="{Binding BlueRectVisibility}" />
    <Rectangle Grid.Column="1" Fill="Red" Visibility="{Binding RedRectVisibility}"/>
</Grid>

有时,其中一个矩形可以通过绑定将其可见性设置为"塌陷"。那么我想要的是另一个占据所有宽度。有了Xaml,可见的矩形只占屏幕的一半。

将ColumnDefinitions更改为Auto无效,因为Grid不再占用屏幕宽度的100%。

你能解释一下如何制作一个"动态"的用户界面吗?

如何在Xaml中使用折叠控件调整UI

Auto不起作用的原因是布局如下:

  1. Page:嘿,Grid,你想变成多大
  2. Grid:不,让我问问ColumnDefinition。你想有多大
  3. ColumnDefinition:天啊,我不确定;我需要问Rectangle。嘿,Rectangle,你需要多少空间
  4. Rectange:呃,我真的不在乎
  5. ColumnDefinition:那就是零
  6. 以此类推

所以你最终得到了一个零宽度的列。解决方案是动态绑定宽度@Tam Bui有正确的方法,但这里是Windows Phone 8.1的简化版本:

XAML

<StackPanel>
  <Grid Height="100">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="{Binding FirstColumnWidth}" />
      <ColumnDefinition Width="{Binding SecondColumnWidth}"/>
    </Grid.ColumnDefinitions>
    <Rectangle VerticalAlignment="Stretch" 
      HorizontalAlignment="Stretch" Fill="Blue" />
    <Rectangle VerticalAlignment="Stretch" 
      HorizontalAlignment="Stretch" Fill="Red" Grid.Column="1"/>
  </Grid>
  <Button Content="toggle column width" Click="ToggleColWidth"/>
</StackPanel>

代码

public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
  GridLength firstWidth;
  GridLength secondWidth;
  public MainPage()
  {
    firstWidth = secondWidth = new GridLength(1, GridUnitType.Star);
    DataContext = this;
    InitializeComponent();
  }
  void RaisePropertyChanged([CallerMemberName] string name = "")
  {
    var handler = PropertyChanged;
    if (handler != null)
      handler(this, new PropertyChangedEventArgs(name));
  }
  public event PropertyChangedEventHandler PropertyChanged;
  public GridLength FirstColumnWidth
  {
    get { return firstWidth; }
    set { firstWidth = value; RaisePropertyChanged(); }
  }
  public GridLength SecondColumnWidth
  {
    get { return secondWidth; }
    set { secondWidth = value; RaisePropertyChanged(); }
  }
  private void ToggleColWidth(object sender, RoutedEventArgs e)
  {
    if (FirstColumnWidth.GridUnitType == GridUnitType.Star)
    {
      FirstColumnWidth = new GridLength(0, GridUnitType.Pixel);
      SecondColumnWidth = new GridLength(1, GridUnitType.Star);
    }
    else
    {
      FirstColumnWidth = SecondColumnWidth = new GridLength(1, GridUnitType.Star);
    }
  }
}

使用这种方法,您甚至不需要更改矩形的Visibility

我认为问题的根源在于您将网格的列定义为50%,因此一旦建立了这一点,那么更改矩形的可见性就不会有任何区别。我使用WPF制作了这个小POC(不确定是否所有命令都能转换为Silverlight,但您可以尝试一下(。基本上,我关注的是扰乱列的宽度,而不是矩形的可见性。

在您的xaml文件中:

<Window x:Class="CollapsibleRegion.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:CollapsibleRegion"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.InputBindings>
    <KeyBinding Modifiers="Ctrl" Key="B" Command="{Binding ToggleWidthCommand}" CommandParameter="Blue"/>
    <KeyBinding Modifiers="Ctrl" Key="R" Command="{Binding ToggleWidthCommand}" CommandParameter="Red"/>
</Window.InputBindings>
<Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="blueColumn" Width="{Binding BlueColumnWidth}" />
            <ColumnDefinition x:Name="redColumn" Width="{Binding RedColumnWidth}" />
        </Grid.ColumnDefinitions>
        <Rectangle Grid.Column="0" Fill="Blue" />
        <Rectangle Grid.Column="1" Fill="Red" />
    </Grid>
</Grid>
</Window>

在您的代码隐藏(xaml.cs(中:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private GridLength blueColumnWidth;
    private GridLength redColumnWidth;
    private ToggleWidthCommand toggleWidthCommand;
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        this.BlueColumnWidth = new GridLength(5, GridUnitType.Star);
        this.RedColumnWidth = new GridLength(5, GridUnitType.Star);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    public GridLength BlueColumnWidth
    {
        get
        {
            return this.blueColumnWidth;
        }
        set
        {
            this.blueColumnWidth = value; OnPropertyChanged();
        }
    }
    public GridLength RedColumnWidth
    {
        get
        {
            return this.redColumnWidth;
        }
        set
        {
            this.redColumnWidth = value; OnPropertyChanged();
        }
    }
    public ToggleWidthCommand ToggleWidthCommand
    {
        get
        {
            if (this.toggleWidthCommand == null)
            {
                this.toggleWidthCommand = new ToggleWidthCommand(this);
            }
            return this.toggleWidthCommand;
        }
    }
    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

最后,对于ToggleWidthCommand.cs,添加以下内容:

public class ToggleWidthCommand : ICommand
{
    private MainWindow parent;
    public ToggleWidthCommand(MainWindow parent)
    {
        this.parent = parent;
    }
    public event EventHandler CanExecuteChanged;
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public void Execute(object parameter)
    {
        var blueOrRed = (string)parameter;
        if (blueOrRed == "Blue")
        {
            if (this.parent.BlueColumnWidth.Value == 0)
                this.parent.BlueColumnWidth = new System.Windows.GridLength(5, System.Windows.GridUnitType.Star);
            else
                this.parent.BlueColumnWidth = new System.Windows.GridLength(0, System.Windows.GridUnitType.Pixel);
        }
        if (blueOrRed == "Red")
        {
            if (this.parent.RedColumnWidth.Value == 0)
                this.parent.RedColumnWidth = new System.Windows.GridLength(5, System.Windows.GridUnitType.Star);
            else
                this.parent.RedColumnWidth = new System.Windows.GridLength(0, System.Windows.GridUnitType.Pixel);
        }
    }
}

这只是一个概念的证明,所以显然有更有效/更干净/可扩展的方法来实现这种行为,但我只是想快速做出回应,向你展示如何做到这一点。希望它对你有用!