WPF布局 - 获取列以填充可用空间

时间:2009-12-04 00:27:13

标签: wpf layout listbox controltemplate autosize

我有一个ListBox,其模板中有一个网格,允许有4列。一列是ListBox的实际文本。我希望该列填充可用的水平空间。

列定义为:

<ControlTemplate TargetType="ListBoxItem">
    <Grid ScrollViewer.CanContentScroll="True" Margin="2">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20" />
            <ColumnDefinition Width="50" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="30" />
        </Grid.ColumnDefinitions>
        <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding IsSelected,
                  RelativeSource={RelativeSource TemplatedParent},
                  Mode=TwoWay}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="{Binding Id}" />
        <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="{Binding Title}" />
        <Button HorizontalAlignment="Right" Grid.Column="3" Tag="{Binding Id}" Margin="5,0,5,0">-&gt;</Button>
    </Grid>
</ControlTemplate>

我尝试了几种这样的排列,除了明确的大小设置外,没有什么能在窗口中修复它。然后,当我调整窗口大小时,它不会随之调整大小。

ListBox包含在ScrollViewer中以允许垂直滚动(我猜这就是弄乱我的。)

有关如何让第三列填充可用空间的任何想法,而不是更多?

4 个答案:

答案 0 :(得分:1)

您是否需要ListBox的控制行为,或者您是否仅将其用于布局。

如果您仅将其用于布局,则可以将ListBox替换为ItemsControl内的ScrollViewer

此代码(已在设计师中工作)显示:

<ScrollViewer>
    <ItemsControl>
        <!--<ListBox>-->
        <Grid Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>

            <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="True" />
            <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="5,0,5,0" Text="Id" />
            <TextBlock VerticalAlignment="Center" Grid.Column="2" Margin="5,0,5,0" Text="Title" />
            <Button HorizontalAlignment="Right" Grid.Column="3" Margin="5,0,5,0">-&gt;</Button>
        </Grid>
        <!--</ListBox>-->
    </ItemsControl>
</ScrollViewer>

ListBox有一些可以杀死其子项宽度的属性,就像TreeView一样。因此,如果您可以避免使用它,仅出于布局原因,这可能是您最快的选择。

否则你需要将Grid的宽度数据绑定到ListView之外的虚拟对象的宽度,但是当滚动条出现/消失时,凌乱的一方正在处理宽度变化

答案 1 :(得分:1)

为什么需要将ListBox包装在ScrollViewer中?当ListList内容不适合可用空间时,ListBox会自动显示ScrollViewer。您可以将其从XAML中删除,它仍然可以正常工作。至少,它对我有用。 :)

我尝试了你的ControlTemplate,它看起来效果很好。问题是,当第3列调整为ListBox的宽度时,如果第3列中的文本非常长,则第4列将不会出现,直到所有文本都可见。

我还尝试了另一种布局方法,我不确定在性能方面,但我的想法是使用DockPanel而不是Grid。我在XAML中添加了第三列以使其填充剩余空间,并将其停靠在左侧(我将第4列停靠在右侧)。它仍然希望在第3列中显示整个字符串。我不知道为什么会发生这种情况,以及当可用空间不足以显示文本时,为什么文本不会换行或使用省略号。

<Window.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <DockPanel Width="Auto">
                        <CheckBox Width="20" VerticalAlignment="Center" DockPanel.Dock="Left" IsChecked="{Binding IsSelected,
                                        RelativeSource={RelativeSource TemplatedParent},
                                        Mode=TwoWay}" />
                        <TextBlock Width="50" VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="hi" />
                        <Button Width="30" HorizontalAlignment="Right" DockPanel.Dock="Right" Margin="5,0,5,0">-&gt;</Button>
                        <TextBlock VerticalAlignment="Center" DockPanel.Dock="Left" Margin="5,0,5,0" Text="afdjfksdhahjklfadshjlasffasdlhjsafdlhjasdfasfhdjlaslfhdjsfdhjlsfdlhjsfdhjsfdddsd" TextTrimming="CharacterEllipsis" TextWrapping="WrapWithOverflow" />
                    </DockPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>   

答案 2 :(得分:0)

是的我建议滚动查看器弄乱你,你可以将网格的宽度绑定到父对象的实际宽度,所以有一个定义的大小,其中*必须实际填充。

答案 3 :(得分:0)

我终于搞清楚了。

包含列表框需要将水平滚动条设置为禁用,如下所示:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" 

一旦我这样做,网格大小完美。

有一天我会弄清楚所有这些“声明性的东西”是如何运作的。