优化性能:控件
更新: 2008 年 7 月
Windows Presentation Foundation (WPF) 包括很多公共用户界面 (UI) 组件,这些组件在大多数 Windows 应用程序中使用。本主题介绍一些改进用户界面性能的技术。
本主题包括下列各节。
- 显示大型数据集
- 容器回收
- 支持双向虚拟化
- 优化模板
- 延迟滚动
- 实现性能功能的控件
- 相关主题
显示大型数据集
WPF 控件(如 ListView 和 ComboBox)用于在应用程序中显示项列表。如果要显示的列表很大,则应用程序的性能可能会受到影响。这是因为标准布局系统会为每个与列表控件关联的项创建一个布局容器,并计算其布局大小和位置。一般来说,您不需要同时显示所有的项,而只需显示一个子集,用户可滚动查看列表。在这种情况下,使用用户界面虚拟化很有意义,这意味着项容器生成和项的关联布局计算会推迟到相应项可见的时候进行。
用户界面虚拟化是列表控件的一个重要方面。不应将用户界面虚拟化与数据虚拟化混淆。用户界面虚拟化只将可见项存储在内存中,但在数据绑定应用场景中,它会将整个数据结构存储在内存中。相反,数据虚拟化只将屏幕上可见的数据项存储在内存中。
默认情况下,只有当 ListView 和 ListBox 控件的列表项绑定到数据时,才会对这些控件启用用户界面虚拟化。可以通过将 VirtualizingStackPanel.IsVirtualizing 附加属性设置为 true,来启用 TreeView 虚拟化。如果要对派生自 ItemsControl 的自定义控件或使用 StackPanel 类的现有项控件(如 ComboBox)启用用户界面虚拟化,可将 ItemsPanel 设置为 VirtualizingStackPanel,并将 IsVirtualizing 设置为 true。遗憾的是,您可能会在没有意识到的情况下对这些控件禁用用户界面虚拟化。以下是禁用用户界面虚拟化的条件的列表。
项容器直接添加到 ItemsControl。例如,如果应用程序将 ListBoxItem 对象显式添加到 ListBox,则 ListBox 不会虚拟化 ListBoxItem 对象。有关项容器的更多信息,请参见控件内容模型概述中的“ItemsControl”部分。
将 CanContentScroll 设置为 false。
将 IsVirtualizing 设置为 false。
使用项分组。
当前,没有 WPF 控件提供对数据虚拟化的内置支持。
容器回收
“容器回收”是 .NET Framework 3.5 SP1 针对继承自 ItemsControl 的控件新增的一项用户界面虚拟化优化功能,它还可以改进滚动性能。在填充使用用户界面虚拟化的 ItemsControl 时,它会为滚动到视图中的每个项创建一个项容器,并销毁滚动到视图之外的每个项的项容器。通过容器回收,控件能够将现有项容器重复用于不同的数据项,因此当用户滚动 ItemsControl 时,不会反复地创建和销毁项容器。可以选择通过将 VirtualizationMode 设置为 Recycling 来启用项回收。
只要存在以下任何一种情况,就不使用容器回收:
项容器直接添加到 ItemsControl。例如,ListBoxItem 对象直接添加到 ListBox 控件。有关项容器的更多信息,请参见控件内容模型概述中的“ItemsControl”部分。
ItemsControl 中的项容器属于不同类型。例如,使用 Separator 对象的 Menu 无法实现项回收,因为 Menu 包含 Separator 和 MenuItem 类型的对象。
在回收项容器时,要考虑的一个重要因素是,您是否具有与属于该项的项容器相关联的其他状态信息。在这种情况下,必须保存其他状态。例如,您可能有一个包含在 Expander 控件中的项,IsExpanded 状态绑定到该项的容器,而不是绑定到该项本身。当将该容器重用于新项时,IsExpanded 的当前值也用于新项。此外,旧项会丢失正确的 IsExpanded 值。
任何支持虚拟化的 ItemsControl 都可以使用容器回收。有关如何在 ListBox 上启用容器回收的示例,请参见如何:提高 ListBox 的滚动性能。
支持双向虚拟化
VirtualizingStackPanel 提供对一个方向(水平或垂直)上的用户界面虚拟化的内置支持。如果您要对控件使用双向虚拟化,则必须实现一个扩展 VirtualizingStackPanel 类的自定义面板。VirtualizingStackPanel 类公开虚方法,例如 OnViewportSizeChanged、LineUp、PageUp 和 MouseWheelUp。这些虚方法使您能够检测列表的可见部分中的更改,并相应地进行处理。
优化模板
可视化树中包含应用程序中的所有可视元素。除了直接创建的对象之外,它还包含由于模板扩展而创建的对象。例如,在创建 Button 时,可视化树中还包含 ClassicBorderDecorator 和 ContentPresenter 对象。如果您尚未优化控件模板,则可能在可视化树中创建大量不必要的额外对象。可以使用 XAMLPad 来跟踪可视化树中的元素,并尽可能移除模板中不必要的项。有关可视化树的更多信息,请参见 Windows Presentation Foundation 图形呈现概述。
延迟滚动
默认情况下,当用户拖动滚动条上的滚动块时,内容视图会不断更新。如果控件中的滚动速度很慢,请考虑使用延迟滚动。在延迟滚动中,只有当用户松开滚动块时,内容才会更新。
若要实现延迟滚动,请将 IsDeferredScrollingEnabled 属性设置为 true。IsDeferredScrollingEnabled 是一个附加属性,可在 ScrollViewer 上设置,也可在其控件模板中具有 ScrollViewer 的任何控件上设置。
实现性能功能的控件
下表列出了用于显示数据的公共控件,以及它们对性能功能的支持。有关如何启用这些功能的信息,请参见上面几部分。
控件 |
虚拟化 |
容器回收 |
延迟滚动 |
---|---|---|---|
可以启用 |
可以启用 |
可以启用 |
|
可以启用 |
可以启用 |
可以启用 |
|
不可用 |
不可用 |
可以启用 |
|
默认 |
可以启用 |
可以启用 |
|
默认 |
可以启用 |
可以启用 |
|
可以启用 |
可以启用 |
可以启用 |
|
不可用 |
不可用 |
可以启用 |
说明: |
---|
有关如何在 TreeView 上启用虚拟化和容器回收的示例,请参见如何:提高 TreeView 的性能。 |
请参见
概念
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
2008 年 7 月 |
增加了关于 .NET Framework 3.5 Service Pack 1 的主题。 |
SP1 功能更改。 |