WPF 网格布局查询
WPF Grid Layout query
在 WPF 项目中,我有一个 Grid
定义为两行,每行包含一个 ListBox
。 RowDefinition
有自己的 Height = '*'
,因此每个 ListBox
都分配了相等的 space。然而,我想要发生的是,当 ListBox
中的任何一个并不完全需要它自己的 space(通过在运行时删除项目)时,那么 'spare' space 是交给另一个 ListBox
.
因此,使用我在下面列出的代码,两个 ListBox
都以相等的 space 开始,这是正确的。按下该按钮会从顶部 ListBox
(topList) 中删除一些条目,从而在其余 2 个条目下方显示白色 space。就是这个space我想被授予最底层ListBox
。反之亦然。
XAML:
<Window x:Class="FiftyPercentSplit.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:FiftyPercentSplit"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid Height="200">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Delete from Top List"/>
<ListBox x:Name="topList" Grid.Row="1">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="2">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
</Grid>
</Window>
后面的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnDeleteFromTopList_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 7; i++)
{
topList.Items.RemoveAt(0);
}
}
}
只需像这样使用 StackPanel 而不是 Grid:
<Window x:Class="WpfApplication2.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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel Height="200">
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Delete from Top List"/>
<ListBox x:Name="topList" Grid.Row="1">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="2">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
</StackPanel>
实际上,第二行应该表现为 Auto
-height 行。但是像 ListBox 这样的可滚动控件在 Auto
-height 行中不能很好地工作——它们无限增长并且不显示滚动。为了克服它,我通常必须设置 MaxHeight
.
在这种情况下,我留下了 2 个带有 Height="*" 的 RowDefinitions,使用名称为 Measurer
的元素来获取行的实际高度,并将 MaxHeight
设置为 topList
来自ActualHeight
的测量者。另请注意,我使用了带有 <RowDefinition Height="Auto"/>
的嵌套网格
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Del"/>
<Border Grid.Row="2" Name="Measurer"/>
<Grid Grid.Row="1" Grid.RowSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="topList" VerticalAlignment="Top"
MaxHeight="{Binding ActualHeight, ElementName=Measurer}">
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="1">
</ListBox>
</Grid>
</Grid>
- 从示例中删除了 ListBoxItems 以避免答案中的代码混乱
在 WPF 项目中,我有一个 Grid
定义为两行,每行包含一个 ListBox
。 RowDefinition
有自己的 Height = '*'
,因此每个 ListBox
都分配了相等的 space。然而,我想要发生的是,当 ListBox
中的任何一个并不完全需要它自己的 space(通过在运行时删除项目)时,那么 'spare' space 是交给另一个 ListBox
.
因此,使用我在下面列出的代码,两个 ListBox
都以相等的 space 开始,这是正确的。按下该按钮会从顶部 ListBox
(topList) 中删除一些条目,从而在其余 2 个条目下方显示白色 space。就是这个space我想被授予最底层ListBox
。反之亦然。
XAML:
<Window x:Class="FiftyPercentSplit.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:FiftyPercentSplit"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid Height="200">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Delete from Top List"/>
<ListBox x:Name="topList" Grid.Row="1">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="2">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
</Grid>
</Window>
后面的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnDeleteFromTopList_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 7; i++)
{
topList.Items.RemoveAt(0);
}
}
}
只需像这样使用 StackPanel 而不是 Grid:
<Window x:Class="WpfApplication2.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"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel Height="200">
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Delete from Top List"/>
<ListBox x:Name="topList" Grid.Row="1">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="2">
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
<ListBoxItem>4</ListBoxItem>
<ListBoxItem>5</ListBoxItem>
<ListBoxItem>6</ListBoxItem>
<ListBoxItem>7</ListBoxItem>
<ListBoxItem>8</ListBoxItem>
<ListBoxItem>9</ListBoxItem>
</ListBox>
</StackPanel>
实际上,第二行应该表现为 Auto
-height 行。但是像 ListBox 这样的可滚动控件在 Auto
-height 行中不能很好地工作——它们无限增长并且不显示滚动。为了克服它,我通常必须设置 MaxHeight
.
在这种情况下,我留下了 2 个带有 Height="*" 的 RowDefinitions,使用名称为 Measurer
的元素来获取行的实际高度,并将 MaxHeight
设置为 topList
来自ActualHeight
的测量者。另请注意,我使用了带有 <RowDefinition Height="Auto"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnDeleteFromTopList" Click="btnDeleteFromTopList_Click" Content="Del"/>
<Border Grid.Row="2" Name="Measurer"/>
<Grid Grid.Row="1" Grid.RowSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" x:Name="topList" VerticalAlignment="Top"
MaxHeight="{Binding ActualHeight, ElementName=Measurer}">
</ListBox>
<ListBox x:Name="bottomList" Grid.Row="1">
</ListBox>
</Grid>
</Grid>
- 从示例中删除了 ListBoxItems 以避免答案中的代码混乱