WPF如何虚拟化ItemsControl

我有774个项目的List。当我将其设置为绑定到Items的ViewModel的List属性(也是ItemsSource)时,大约需要10秒钟以上的时间。

我已经尝试过Virtualizing an ItemsControl?的答案,但仍然无法正常工作-仍然需要10秒钟以上的时间。

这是未经修改的代码。请注意, ItemsControlScrollViewer 内部。

XAML:

<Grid d:DataContext="{x:Static local:RulesListDesignmodel.Instance}" Background="{StaticResource ForegroundLightBrush}">
        <ScrollViewer VerticalScrollBarVisibility="Auto">
            <ItemsControl ItemsSource="{Binding Items}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <local:RulesListItemControl />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>

C#

ViewModelApplication.CurrentRulesListViewModel.Items = mList;

这是根据Virtualizing an ItemsControl? 的答案修改代码后的XAML(似乎要花10秒钟以上的时间):

<Grid d:DataContext="{x:Static local:RulesListDesignmodel.Instance}" Background="{StaticResource ForegroundLightBrush}">
    <ScrollViewer VerticalScrollBarVisibility="Auto">
        <ItemsControl ItemsSource="{Binding Items}"
                      VirtualizingStackPanel.IsVirtualizing="True"
                      ScrollViewer.CanContentScroll="True">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:RulesListItemControl />
                </DataTemplate>
            </ItemsControl.ItemTemplate>

            <ItemsControl.ItemsPanel>
                <itemspaneltemplate>
                    <VirtualizingStackPanel />
                </itemspaneltemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.Template>
                <ControlTemplate>
                    <Border
        BorderThickness="{TemplateBinding Border.BorderThickness}"
        Padding="{TemplateBinding Control.Padding}"
        BorderBrush="{TemplateBinding Border.BorderBrush}"
        Background="{TemplateBinding Panel.Background}"
        snapsToDevicePixels="True">
                        <ScrollViewer
                Padding="{TemplateBinding Control.Padding}"
                Focusable="False">
                            <ItemsPresenter
                    snapsToDevicePixels="{TemplateBinding UIElement.snapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
        </ItemsControl>
    </ScrollViewer>
</Grid>
iCMS 回答:WPF如何虚拟化ItemsControl

您应该使用ListBoxListView,它们已经集成了ScrollViewer并且默认情况下启用了UI虚拟化。无需使用更基本的ItemsControl

您应该尝试以下操作以使用UI虚拟化:

<ListBox VirtualizingStackPanel.VirtualizationMode="Recycling" />

VirtualizingStackPanel.VirtualizationMode设置为VirtualizationMode.Recycling可以提高滚动性能。

如果您想呆在ItemsControl上(为什么?),则需要对视觉树进行重新设计。

您当前正在使用两个ScrollViewers。一个在模板内部,另一个在ItemsControl周围。请注意,由于ScrollViewer.CanContentScroll默认为false,因此内部ScrollViewer负责禁用UI虚拟化。将CanContentScroll设置为true是必不可少的,因为这会将滚动单位设置为项目(而不是像素)。 VirtualizingStackPanel需要知道可见项目的数量。

您应该卸下外侧ScrollViewer,然后性能会得到显着改善:

<ItemsControl ItemsSource="{Binding Items}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <local:RulesListItemControl />
    </DataTemplate>
  </ItemsControl.ItemTemplate>

  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <VirtualizingStackPanel IsVirtualizing="True"
                              VirtualizationMode="Recycling" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>

  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderThickness="{TemplateBinding BorderThickness}"
              BorderBrush="{TemplateBinding BorderBrush}"
              Background="{TemplateBinding Background}">
        <ScrollViewer CanContentScroll="True" 
                      Padding="{TemplateBinding Padding}"
                      Focusable="False">
          <ItemsPresenter />
        </ScrollViewer>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
</ItemsControl>

但更重要的是,重点放在您的自定义RulesListItemControl上。该控件为每个项目加载。复杂的控件引入了复杂的初始化。您应该尝试减少此控件的视觉树。

删除不需要的每个Border,将Label替换为TextBlock,重新访问触发器等。目标是减少每个项目容器的呈现时间。
为此,您需要覆盖用于组成ControlTemplate的控件中的RulesListItemControl

本文链接:https://www.f2er.com/2007869.html

大家都在问