当DataTemplate具有可见性绑定时,WPF ListBox自动宽度更改不正确

时间:2014-12-28 23:16:14

标签: c# wpf xaml binding

我有一个ListBox停靠在窗口的左边,窗口的宽度应该是它的大小。当我滚动列表框时,它的宽度会摆动并变得比它应该更宽。基本上我认为发生的事情是ListBox计算所有孩子的大小以确定它自己的大小,但似乎只评估实际在屏幕上的控件的可见性绑定(可能是为了提高性能)原因)。结果是它错误地计算了它的屏幕外儿童的大小,为隐藏的控件保留了空间。

如果列表中的项目少于窗口高度(因此没有滚动条),则列表始终是正确的宽度,当您滚动到顶部或底部时,它总是捕捉到正确的宽度。只有在滚动条位于宽度错误的位置之间时才会这样做。

我整个晚上一直在努力解决这个问题,尝试各种重构,例如使用DataTemplateSelector抽象出对可见性绑定的需求,但我最终得到了非常肮脏的解决方法我并不满意用。我想解决手头的实际问题,而不是躲避它。任何指针都会非常感激。

在下面的示例中,列表显示自身的大小为Foo和Bar的宽度。更改StackPanel方向会使其大小变为Foo和Bar中较长的宽度。希望这是有道理的。

<ListBox ItemsSource="{Binding Widgets}" DockPanel.Dock="Left">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Visibility="{Binding ShowFoo, Converter={StaticResource BoolToVisConverter}}" Text="{Binding Foo}" />
                <TextBlock Visibility="{Binding ShowBar, Converter={StaticResource InverseBoolToVisConverter}}" Text="{Binding Bar}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

1 个答案:

答案 0 :(得分:4)

您所描述的此效果与可见性绑定无关。

  

基本上我认为正在发生的是ListBox计算   所有孩子的大小,以确定它自己的大小,但仅限   似乎评估实际上控件的可见性绑定   在屏幕上(可能是出于性能原因)。结果是   它错误地计算了它的屏幕外儿童的大小,   为隐藏的控件保留空间。

这对我来说听起来不错。它是出于性能原因而完成的。也称为ListBox的虚拟化。其他控件也会继承它,例如DataGrid

为了摆脱它,你可以用通常的stackpanel切换VirtualizingStackPanel

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

如果你有大量的物品,你可能会,或者可能不会遭受性能损失,但这就是生命。如果你不喜欢这个,我建议你首先不要有这个要求。