使用虚拟化列表框调整窗口大小

时间:2015-02-12 20:39:27

标签: wpf performance xaml

我有一个WPF应用程序,我使用基本的MVVM原则创建。

在我的一个观点中,我有一个ListBox控件。它绑定到我的ViewModel上的ObservableCollection

粗略地说,布局是这样的:

<UserControl>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding Students}" 
                 ItemTemplate="{StaticResource Template_Student}"  />
        <ListBox ItemsSource="{Binding Logs}" />
    </Grid>
</UserControl>

<DataTemplate x:Key="Template_Student">
    <Grid Width="300" Height="85">
        <Grid.RowDefinitions>

        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Image Grid.RowSpan="3" Margin="5 10"
               Height="65" Width="50"
               Source="{Binding Property7}">
        </Image>
        <StackPanel Grid.Column="1" Margin="2 10 2 2">
            <TextBlock>
                <Run Text="{Binding Property4, StringFormat=\{0\}\,}" FontWeight="Bold" FontSize="14" />
                <Run Text="{Binding Property5}" FontWeight="Bold" FontSize="14" />
                <Run Text="{Binding Property6, StringFormat=(\{0\})}" />
            </TextBlock>
            <TextBlock>
                <Run Text="Property1:" />
                <Run Text="{Binding Property1}" />
            </TextBlock>
            <TextBlock>
                <Run Text="Property2:" />
                <Run Text="{Binding Property2}" />
            </TextBlock>
            <TextBlock>
                <Run Text="Property3:" />
                <Run Text="{Binding Property3, Mode=OneWay}" />
            </TextBlock>
        </StackPanel>
    </Grid>
</DataTemplate>

ListBox使用默认VirtualizingStackPanel,我通过Snoop确认它正在使用它并且VirtualizingStackPanel.IsVirtualizing为真。

ViewModel的Students属性中包含大约1000个对象。他们并不那么沉重。大约11个启用INPC的属性。

在这种情况下,整个窗口的窗口重绘显着滞后。

简单地恢复窗口的大小或最大化它会导致延迟超过秒。向Logs属性(也是非常轻量级对象的ObservableCollection)添加内容,导致窗口重绘时延迟超过一秒。

延迟似乎与两件事有一些关联:

  1. ListBox中的项目数。如果我把它减少到10 物品,滞后完全消失了。如果我做250件,那就是 明显但不可怕。 500开始变坏,1000开始变坏 实际数据集中的数字不可用。
  2. 复杂性 DataTemplate。如果我删除了ImageStackPanel 具有所有属性,性能更好(类似于约 包含所有数据的100个项目)。如果我离开任何一个,那么 表现再次糟糕。
  3. 我想知道这是否与我选择的方式有关(所有Grid ColumnDefinitions都有Width {{1}例如,或Auto。或者,如果可能我只是在做一些完全错误的事情,这会破坏虚拟化。

    任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我几乎完全相同的情况。事实证明,即使没有自定义模板,WPF ListBox对于&gt; 100项也表现不佳。

我不知道任何开源或免费替代品,但我们尝试Xceed Extended WPF Toolkit Plus(商业*)及其替代品Xceed Ultimate ListBox for WPF

它有一堆优化,我们的性能提升是巨大的。在列表和自定义模板中大约有500个项目,调整窗口的大小曾经非常慢。现在它很顺利。

*我与Xceed没有任何关系。