WPF 网格布局查询

WPF Grid Layout query

在 WPF 项目中,我有一个 Grid 定义为两行,每行包含一个 ListBoxRowDefinition 有自己的 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 以避免答案中的代码混乱