虚拟化ItemsControl? [英] Virtualizing an ItemsControl?
问题描述
我有一个ItemsControl
,其中包含要虚拟化的数据列表,但是VirtualizingStackPanel.IsVirtualizing="True"
似乎不适用于ItemsControl
.
I have an ItemsControl
containing a list of data that I would like to virtualize, however VirtualizingStackPanel.IsVirtualizing="True"
does not seem to work with an ItemsControl
.
是真的吗?或者还有另一种我不知道的方式吗?
Is this really the case or is there another way of doing this that I am not aware of?
为了测试,我一直在使用以下代码块:
To test I have been using the following block of code:
<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
,每个项目均被初始化.
If I change the ItemsControl
to a ListBox
, I can see that the Initialized
event only runs a handful of times (the huge margins are just so I only have to go through a few records), however as an ItemsControl
every item gets initialized.
我尝试将ItemsControlPanelTemplate
设置为VirtualizingStackPanel
,但这似乎无济于事.
I have tried setting the ItemsControlPanelTemplate
to a VirtualizingStackPanel
but that doesn't seem to help.
推荐答案
除了让ItemsPanelTemplate
使用VirtualizingStackPanel
之外,实际上还有很多其他功能. ItemsControl
的默认ControlTemplate
没有ScrollViewer
,这是虚拟化的关键.添加到ItemsControl
的默认控制模板(使用ListBox
的控制模板作为模板),可以得到以下信息:
There's actually much more to it than just making the ItemsPanelTemplate
use VirtualizingStackPanel
. The default ControlTemplate
for ItemsControl
does not have a ScrollViewer
, which is the key to virtualization. Adding to the the default control template for ItemsControl
(using the control template for ListBox
as a template) gives us the following:
<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>
(顺便说一句,用于查看默认控制模板的好工具是向我显示模板)
(BTW, a great tool for looking at default control templates is Show Me The Template)
注意事项:
您必须设置ScrollViewer.CanContentScroll="True"
,请参见此处为什么.
You have to set ScrollViewer.CanContentScroll="True"
, see here for why.
还要注意,我放了VirtualizingStackPanel.VirtualizationMode="Recycling"
.这将减少调用TextBlock_Initialized
的次数,但是在屏幕上可以看到许多TextBlock.您可以在此处阅读更多内容
.
Also notice that I put VirtualizingStackPanel.VirtualizationMode="Recycling"
. This will reduce the numbers of times TextBlock_Initialized
is called to however many TextBlocks are visible on the screen. You can read more on UI virtualization here
.
忘记说清楚了:作为替代解决方案,您可以将ItemsControl
替换为ListBox
:)
另外,请查看在MSDN上优化性能页,请注意,ItemsControl
不在实现性能功能的控件"中,表格,这就是我们需要编辑控件模板的原因.
Forgot to state the obvious: as an alternate solution, you can just replace ItemsControl
with ListBox
:)
Also, check out this Optimizing Performance on MSDN page and notice that ItemsControl
isn't in the "Controls That Implement Performance Features" table, which is why we need to edit the control template.
这篇关于虚拟化ItemsControl?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!