如何通过重新定义的列表框模板使用 UI 虚拟化
How to use UI virtualization with redefined ListBox templates
我正在尝试将 ListBox 用作包含多个项目的视图,当然,我需要在其中使用 UI 虚拟化。
问题是只有当我这样声明 ListBox 时虚拟化才有效:
<ListBox
ItemsSource="{Binding ItemsSource}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
但是如果我尝试自定义它,它就不再虚拟化了:
<ListBox
ItemsSource="{Binding ItemsSource}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
据我所知,此示例包含的内容与 ListBox 默认包含的内容相同。但是虚拟化不起作用。我在这里阅读了几篇文章和几个答案,但仍然无法弄清楚 "general way" - 我必须设置、绑定、添加什么和在哪里才能使虚拟化与自定义模板一起工作?
原因是您正在为 ItemsPanel
使用 StackPanel
- 您应该使用 VirtualizingStackPanel
(这也是 ListBox 的默认 ItemsPanel)。
删除您的 ItemsPanel
定义或修改它以使用 VirtualizingStackPanel
:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
两件事:
更新您的 PanelTemplate
以使用 VirtualizingStackPanel
并将您的 virtualization
选项添加到 ControlTemplate
的 ScrollViewer
。
<ListBox.Template>
<ControlTemplate>
<ScrollViewer VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>
我正在尝试将 ListBox 用作包含多个项目的视图,当然,我需要在其中使用 UI 虚拟化。
问题是只有当我这样声明 ListBox 时虚拟化才有效:
<ListBox
ItemsSource="{Binding ItemsSource}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
但是如果我尝试自定义它,它就不再虚拟化了:
<ListBox
ItemsSource="{Binding ItemsSource}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
据我所知,此示例包含的内容与 ListBox 默认包含的内容相同。但是虚拟化不起作用。我在这里阅读了几篇文章和几个答案,但仍然无法弄清楚 "general way" - 我必须设置、绑定、添加什么和在哪里才能使虚拟化与自定义模板一起工作?
原因是您正在为 ItemsPanel
使用 StackPanel
- 您应该使用 VirtualizingStackPanel
(这也是 ListBox 的默认 ItemsPanel)。
删除您的 ItemsPanel
定义或修改它以使用 VirtualizingStackPanel
:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
两件事:
更新您的 PanelTemplate
以使用 VirtualizingStackPanel
并将您的 virtualization
选项添加到 ControlTemplate
的 ScrollViewer
。
<ListBox.Template>
<ControlTemplate>
<ScrollViewer VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<views:SiteEntryView />
</DataTemplate>
</ListBox.ItemTemplate>