WPF如何使ListBox在Grid.Row中高度自适应?

13

我试图将一个ListBox的高度拉伸到父网格的100%高度(即父视图的90%高度),即使listboxes为空也要实现。值得注意的是,VerticalAlignment ="Stretch"似乎不起作用,因此已从ListBoxStackPanel元素中删除它。目前,ListBox只能拉伸到容纳其项数所需的高度。我知道行定义应该起作用,但如果两个列表都为空,它们都会收缩到几像素高(连同网格行一起)。可能有什么原因导致这些行尽管明确声明了高度却收缩了吗?

<Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>
    <ListBox Grid.Column="0" Grid.Row="0" Name="Subdivisions" SelectedItem="{Binding SelectedSubdivisionViewModel}" ItemsSource="{Binding Path=Subdivisions}" Grid.IsSharedSizeScope="True">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Border BorderBrush="#FF4788c8" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8">
                        <Expander IsExpanded="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">
                            <Expander.Header>
                                <StackPanel>
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*" SharedSizeGroup="col1" />
                                            <ColumnDefinition Width=".1*" SharedSizeGroup="col2" />
                                            <ColumnDefinition Width="*" SharedSizeGroup="col3" />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition/>
                                            <RowDefinition/>
                                        </Grid.RowDefinitions>
                                        <TextBlock Grid.Column="0" Grid.Row="0">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="Name: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                        <TextBlock Grid.Column="2" Grid.Row="0">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="ID: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                        <TextBlock Grid.Column="2" Grid.Row="1">
                                            <TextBlock.Text>
                                                <MultiBinding StringFormat="ID: {0}">
                                                  <Binding Path="SubdivisionName" />
                                                  <Binding Path="SubdivisionID" />
                                                </MultiBinding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </Grid>
                                </StackPanel>
                            </Expander.Header>
                            <StackPanel>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition />
                                        <RowDefinition />
                                    </Grid.RowDefinitions>
                                    <TextBlock Text="{Binding ElementName=SubdivisionID}" />
                                    <TextBlock Text="{Binding Path=SubdivisionID}" />
                                </Grid>
                            </StackPanel>
                        </Expander>
                    </Border>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

你看到的是什么?当我显示它时,ListBox 的高度占窗口高度的 90%,这正是我在 <RowDefinition Height=".9*"/> 中期望看到的。 - Kimberly
似乎第一行没有遵守90%的高度定义。 - alan
在我的情况下,有一个资源字典中的GroupBox样式被App.xaml引用。VerticalAlignment被设置为Top。我将该属性本地设置为Stretch。这并没有回答问题,但可能会帮助遇到类似问题的人。 - AMissico
3个回答

36

通过以下的XAML,我成功地将ListBox的高度属性绑定到LayoutRoot GridActualHeight以实现所需的高度:

<Grid x:Name="LayoutRoot" Background="LightGray">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>
    <ListBox Name="Subdivisions" SelectedItem="{Binding SelectedSubdivisionViewModel}" ItemsSource="{Binding Path=Subdivisions}" Grid.IsSharedSizeScope="True" Height="{Binding ElementName=LayoutRoot, Path=ActualHeight}" >

重要的部分是:

Height="{Binding ElementName=LayoutRoot, Path=ActualHeight}"

也可以通过祖先类型实现:

Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}}"

如果你希望 ListBox 的高度与行的高度相同,请给这一行命名。然后,在 Binding 中将 ElementName 改为你的名称即可。 - CAG2

13
使用 StackPanel 可以压缩空间。将其移除后,它会填充整个高度。

2
您发布的代码完全按照父表格的行高定义操作:占用可用高度的90%。
*.1 = 高度的10% *.9 = 高度的90%
通常情况下,从xaml中删除混乱并从简单的东西开始有助于布局。以下是一个示例,其中包含您的代码Grid列/行定义,但没有混乱,并带有一些背景颜色以显示整个ListBox。
- 第一个ListBox具有多个项目,而第二个ListBox仅具有几个项目。 - 两个ListBox都在第一行中,并填充可用空间的90%。 - 第二行包含一个网格,该网格填充其余空间; 您可以看到它占用可用空间的10%。
请注意,第一个ListBox未声明列或行索引; 当不使用索引时,它被假定为0,即 Grid.Row ="0" Grid.Column=0 。
<Grid Background="Red">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width=".24*"/>
        <ColumnDefinition Width=".73*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height=".9*"/>
        <RowDefinition Height=".1*"/>
    </Grid.RowDefinitions>

    <ListBox Background="LightGray"
             ItemsSource="{x:Static Fonts.SystemFontFamilies}"/>

    <ListBox Grid.Column="1" Grid.Row="0" Background="LightSlateGray">
        <ListBoxItem>John</ListBoxItem>
        <ListBoxItem>Jane</ListBoxItem>
        <ListBoxItem>Fido</ListBoxItem>
    </ListBox>

    <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Background="Tomato" />

</Grid>

我很感激你的尝试,但是它看起来正确的原因是因为你已经在左侧列表中填充了足够多的项目,以使其达到了声明的90%网格行高的最大值。我需要它能够拉伸到整个网格的高度,即使列表为空也要如此。 - alan
@alan - 一点也不。把第一个ListBox拿出来,第二个ListBox仍然会填满整个垂直空间。不确定为什么会被踩。 - Metro Smurf
@alan - 拿我的例子,运行它。两个列表框都会扩展到填满整个高度。然后将第一个列表框从XAML中移除(绑定到字体的那个),运行示例,第二个列表框仍然填满整个高度。 - Metro Smurf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接