如何在 Xaml 中使用折叠控件调整 UI?
How to adjust UI with collapsed controls in Xaml?
我的项目是针对 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 无效,因为网格不再占用 100% 的屏幕宽度。
你能解释一下如何制作 "dynamic" UI 吗?
我认为问题的根源在于您将网格的列定义为 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);
}
}
}
这只是一个概念验证,所以显然有更多 efficient/cleaner/expandable 方法可以实现此行为,但我只是想快速做出回应以向您展示如何做到这一点.希望对你有用!
Auto
不起作用的原因是因为布局是这样的:
Page
:嘿Grid
,你想多大?
Grid
:不知道,让我问 ColumnDefinition
。你想多大?
ColumnDefinition
:哎呀,我不确定;我需要问 Rectangle
。嘿Rectangle
,你需要多少space?
Rectange
:嗯,我不在乎。
ColumnDefinition
:那就是零!
- 等等备份链
所以你最终得到了一个零宽度的列。解决方案是动态绑定宽度。 有正确的方法,但这是 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
。
我的项目是针对 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 无效,因为网格不再占用 100% 的屏幕宽度。
你能解释一下如何制作 "dynamic" UI 吗?
我认为问题的根源在于您将网格的列定义为 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);
}
}
}
这只是一个概念验证,所以显然有更多 efficient/cleaner/expandable 方法可以实现此行为,但我只是想快速做出回应以向您展示如何做到这一点.希望对你有用!
Auto
不起作用的原因是因为布局是这样的:
Page
:嘿Grid
,你想多大?Grid
:不知道,让我问ColumnDefinition
。你想多大?ColumnDefinition
:哎呀,我不确定;我需要问Rectangle
。嘿Rectangle
,你需要多少space?Rectange
:嗯,我不在乎。ColumnDefinition
:那就是零!- 等等备份链
所以你最终得到了一个零宽度的列。解决方案是动态绑定宽度。
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
。