Windows Presentation Foundation (WPF)包括许多在大多数 Windows 应用程序中使用的常见用户界面(UI)组件。 本主题包含提高 UI 性能的技术。
显示大型数据集
WPF 控件,例如 ListView 和 ComboBox ,用于在应用程序中显示项列表。 如果要显示的列表很大,则应用程序的性能可能会受到影响。 这是因为标准布局系统为每个与列表控件关联的项创建布局容器,并计算其布局大小和位置。 通常,不必同时显示所有项:而是显示子集,用户滚动浏览列表。 在这种情况下,使用 UI 虚拟化是有意义的,这意味着项容器生成和项的关联布局计算将延迟到项可见。
UI 虚拟化是列表控件的重要方面。 UI 虚拟化不应与数据虚拟化混淆。 UI 虚拟化仅存储内存中的可见项,但在数据绑定方案中,会将整个数据结构存储在内存中。 相比之下,数据虚拟化仅存储内存中屏幕上可见的数据项。
默认情况下,当列表项绑定到数据时,将为 ListView 和 ListBox 控件启用 UI 虚拟化。
TreeView 可以通过将 VirtualizingStackPanel.IsVirtualizing 附加属性设置为 true
来启用虚拟化。 如果要为派生自ItemsControl的自定义控件或使用该StackPanel类的现有项控件(例如ComboBox)启用 UI 虚拟化,可以将其设置为ItemsPanelVirtualizingStackPanel和设置为 IsVirtualizingtrue
。 遗憾的是,你可以禁用这些控件的 UI 虚拟化,而无需实现它。 下面是禁用 UI 虚拟化的条件列表。
项目容器会直接添加到ItemsControl。 例如,如果应用程序显式向 a ListBox添加ListBoxItem对象,则ListBox不会虚拟化ListBoxItem对象。
ItemsControl 内的物品容器有不同类型。 例如,使用Separator对象的Menu无法实现项回收,因为Menu包含Separator类型和MenuItem类型的对象。
将CanContentScroll设置为
false
。设置为 IsVirtualizing
false
.
虚拟化项容器时,一个重要考虑因素是是否具有与项所属的项容器关联的其他状态信息。 在这种情况下,必须保存附加状态。 例如,你可能有一个项包含在 Expander 控件中,并且 IsExpanded 状态绑定到该项的容器,而不是项本身。 为新项重复使用容器时,新项的当前值 IsExpanded 将用于新项。 此外,旧项将丢失正确的 IsExpanded 值。
目前,没有 WPF 控件提供对数据虚拟化的内置支持。
容器回收
针对继承自 ItemsControl 的控件,.NET Framework 3.5 SP1 添加的 UI 虚拟化优化是 容器回收,这也可以提高滚动性能。 当使用 UI 虚拟化的 ItemsControl 被填充时,它会为每个滚动到视图中的项创建项容器,并销毁每个滚动出视图的项的项容器。 容器回收 使控件能够对不同的数据项重复使用现有项容器,以便在用户滚动 ItemsControl时不会不断创建和销毁项容器。 通过将附加属性设置为VirtualizationModeRecycling,您可以启用项目回收。
任何支持虚拟化的ItemsControl都可以使用容器回收。 有关如何在 a ListBox上启用容器回收的示例,请参阅 改进 ListBox 的滚动性能。
支持双向虚拟化
VirtualizingStackPanel 提供对 UI 虚拟化的内置支持,可以在水平方向或垂直方向之一进行。 如果您想对控件使用双向虚拟化,您必须实现一个继承VirtualizingStackPanel类的自定义面板。 该VirtualizingStackPanel类公开虚拟方法,例如OnViewportSizeChanged,LineUp和PageUpMouseWheelUp。借助这些虚拟方法,可以检测列表可见部分的更改并相应地处理更改。
优化模板
可视化树包含应用程序中的所有视觉元素。 除了直接创建的对象之外,它还包含由于模板扩展而导致的对象。 例如,创建对象 Button时,还可以在可视化树中获取 ClassicBorderDecorator 和 ContentPresenter 对象。 如果尚未优化控件模板,可能会在可视化树中创建大量不必要的对象。 有关可视化树的详细信息,请参阅 WPF 图形呈现概述。
延迟滚动
默认情况下,当用户在滚动条上拖动拇指时,内容视图会持续更新。 如果控件中的滚动速度较慢,请考虑使用延迟滚动。 在延迟滚动中,仅当用户释放拇指时,才会更新内容。
若要实现延迟滚动,请将 IsDeferredScrollingEnabled 属性设置为 true
。
IsDeferredScrollingEnabled 是一个附加属性,可以设置在 ScrollViewer 和任何在其控件模板中包含 ScrollViewer 的控件上。
实现性能功能的控件
下表列出了用于显示数据的常见控件及其对性能功能的支持。 有关如何启用这些功能的信息,请参阅前面的部分。
控制 | 虚拟化 | 容器回收 | 延迟滚动 |
---|---|---|---|
ComboBox | 可以启用 | 可以启用 | 可以启用 |
ContextMenu | 可以启用 | 可以启用 | 可以启用 |
DocumentViewer | 不可用 | 不可用 | 可以启用 |
ListBox | 违约 | 可以启用 | 可以启用 |
ListView | 违约 | 可以启用 | 可以启用 |
TreeView | 可以启用 | 可以启用 | 可以启用 |
ToolBar | 不可用 | 不可用 | 可以启用 |
注释
有关如何在树 TreeView视图上启用虚拟化和容器回收的示例,请参阅 “提高 TreeView 的性能”。