我有一个包含要虚拟化的数据列表的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
,但似乎无济于事。
发布于 2010-05-07 04:25:14
实际上,除了让ItemsPanelTemplate
使用VirtualizingStackPanel
之外,还有很多事情要做。ItemsControl
的默认ControlTemplate
没有ScrollViewer
,这是虚拟化的关键。添加到ItemsControl
的默认控件模板(使用ListBox
的控件模板作为模板)将为我们提供以下内容:
<ItemsControl ItemsSource="{Binding AccountViews.Tables[0]}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Initialized="TextBlock_Initialized"
Text="{Binding Name}" />
</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>
(顺便说一句,查看默认控件模板的一个很好的工具是Show Me The Template)
注意事项:
您必须设置ScrollViewer.CanContentScroll="True"
,请参阅here了解原因。
另请注意,我将VirtualizingStackPanel.VirtualizationMode="Recycling"
。无论屏幕上显示多少个TextBlocks,这都将减少调用TextBlock_Initialized
的次数。你可以阅读更多关于UI虚拟化here 的内容。
编辑:忘记陈述显而易见的事实:作为替代解决方案,您可以将ItemsControl
替换为ListBox
:)另外,查看此Optimizing Performance on MSDN page,并注意到ItemsControl
不在“实现性能特性的控件”表中,这就是我们需要编辑控件模板的原因。
发布于 2012-11-15 14:00:58
基于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>
我不喜欢使用ListBox的建议,因为它们允许在您不一定需要的地方选择行。
发布于 2010-05-07 04:15:16
只是默认的ItemsPanel
不是VirtualizingStackPanel
。您需要更改它:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
https://stackoverflow.com/questions/2783845
复制相似问题