虚拟化itemscontrol?
-
03-10-2019 - |
题
我有一个 ItemsControl
包含我想虚拟化的数据列表,但是 VirtualizingStackPanel.IsVirtualizing="True"
似乎不适合 ItemsControl
.
是真的,还是我不知道的另一种方法?
要测试我一直在使用以下代码块:
<ItemsControl ItemsSource="{Binding Path=AccountViews.Tables[0]}"
VirtualizingStackPanel.IsVirtualizing="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Initialized="TextBlock_Initialized"
Margin="5,50,5,50" Text="{Binding Path=Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
如果我更改 ItemsControl
到 ListBox
, ,我可以看到 Initialized
活动只运行几次(巨大的利润是这样,我只需要查看一些记录),但是作为一个 ItemsControl
每个项目都会初始化。
我尝试设置 ItemsControlPanelTemplate
到 VirtualizingStackPanel
但这似乎无济于事。
解决方案
实际上,它不仅仅是制作 ItemsPanelTemplate
采用 VirtualizingStackPanel
. 。默认值 ControlTemplate
为了 ItemsControl
没有 ScrollViewer
, ,这是虚拟化的关键。添加到默认控制模板 ItemsControl
(使用控制模板 ListBox
作为模板)为我们提供以下内容:
<ItemsControl
VirtualizingStackPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="True"
ItemsSource="{Binding Path=AccountViews.Tables[0]}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock
Initialized="TextBlock_Initialized"
Text="{Binding Path=Name}" />
</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.CanContentScroll="True"
, , 看 这里 为什么。
另请注意我放 VirtualizingStackPanel.VirtualizationMode="Recycling"
. 。这将减少次数 TextBlock_Initialized
但是,在屏幕上可见许多文本块。您可以阅读有关UI虚拟化的更多信息 这里.
编辑:忘记说明明显:作为替代解决方案,您可以替换 ItemsControl
和 ListBox
:)另外,查看 在MSDN页面上优化性能 并注意 ItemsControl
不在“实现性能功能的控件”表中,这就是为什么我们需要编辑控制模板的原因。
其他提示
以Davidn的答案为基础,这是您可以在ItemScontrol上使用的样式来虚拟化:
<!--Virtualised ItemsControl-->
<Style x:Key="ItemsControlVirtualizedStyle" TargetType="ItemsControl">
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<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>
</Setter.Value>
</Setter>
</Style>
我不喜欢使用列表框的建议,因为它们允许您在不一定需要的地方选择行。
只是默认 ItemsPanel
不是 VirtualizingStackPanel
. 。您需要更改它:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>