WPF性能优化の虚拟化
https://docs.microsoft.com/zh-cn/dotnet/desktop/wpf/advanced/optimizing-performance-controls?view=netframeworkdesktop-4.8
显示大型数据集
WPF 控件(如 ListView 和) ComboBox 用于显示应用程序中的项列表。 如果要显示的列表较大,则应用程序性能可能受到影响。 这是因为标准布局系统会为每个与列表控件关联的项创建布局容器,并计算其布局大小和位置。 通常,无需同时显示所有项,而是显示子集,然后用户滚动浏览列表。 这种情况下,使用 UI 虚拟化具有意义,这意味着生成项容器,且项的关联布局计算会推迟,直到项可见时。
UI 虚拟化是列表控件的一个重要方面。 不应混淆 UI 虚拟化和数据虚拟化。 UI 虚拟化在内存中仅存储可见项,但在数据绑定方案中会存储内存中的整个数据结构。 相反,数据虚拟化仅存储内存中屏幕上可见的数据项。
默认情况下,会在 ListView ListBox 其列表项绑定到数据时为和控件启用 UI 虚拟化。 TreeView 可以通过将 VirtualizingStackPanel.IsVirtualizing 附加属性设置为来启用虚拟化 true
。 如果要为派生自的自定义控件 ItemsControl 或使用类的现有项控件(如)启用 UI 虚拟化 StackPanel , ComboBox 则可以将设置 ItemsPanel 为 VirtualizingStackPanel 并将设置 IsVirtualizing 为 true
。 遗憾的是,可对没有实现虚拟化的控件禁用 UI 虚拟化。 以下为禁用 UI 虚拟化的条件列表。
-
项容器直接添加到中 ItemsControl 。 例如,如果应用程序将对象显式添加 ListBoxItem 到 ListBox ,则不 ListBox 会将对象虚拟化 ListBoxItem 。
-
中的项容器 ItemsControl 的类型不同。 例如, Menu 使用 Separator 对象的不能实现项回收,因为 Menu 包含类型为和的对象 Separator MenuItem 。
-
将设置 CanContentScroll 为
false
。 -
将设置 IsVirtualizing 为
false
。
虚拟化项容器时需要考虑到一个重要因素,即是否具有与属于项的项容器相关联的其他状态信息。 这种情况下,必须保存其他状态。 例如,你可能有一个包含在控件中的项, Expander 并且该 IsExpanded 状态绑定到项的容器,而不是绑定到项本身。 当对新项重用容器时,的当前值 IsExpanded 将用于新项。 此外,旧项丢失了正确的 IsExpanded 值。
当前,无任何 WPF 控件提供对数据虚拟化的内置支持。
容器回收
在从继承的控件的 .NET Framework 3.5 SP1 中添加的 UI 虚拟化优化 ItemsControl 是 容器回收, 这还可以提高滚动性能。 当 ItemsControl 填充使用 UI 虚拟化的时,它会为滚动到视图中的每个项创建一个项容器,并为每个滚动到视图之外的项销毁项容器。 容器回收 使控件可以为不同数据项重复使用现有项容器,以便在用户滚动时不会不断创建和销毁项容器 ItemsControl 。 可以通过将附加属性设置为来选择启用项目回收 VirtualizationMode Recycling 。
ItemsControl支持虚拟化的任何都可以使用容器回收。 有关如何在上启用容器回收的示例 ListBox ,请参阅 改善 ListBox 的滚动性能。
支持双向虚拟化
VirtualizingStackPanel 以水平或垂直方式为一个方向的 UI 虚拟化提供内置支持。 如果要对控件使用双向虚拟化,必须实现扩展类的自定义面板 VirtualizingStackPanel 。 VirtualizingStackPanel类公开了虚方法,例如 OnViewportSizeChanged 、 LineUp 、 PageUp 和 MouseWheelUp 。利用这些虚方法,你可以检测列表的可见部分中的更改并相应地对其进行处理。
优化模板
可视化树包含应用程序中所有可视元素。 除直接创建的对象外,它还包括由于模板扩展而产生的对象。 例如,在创建时 Button ,还会 ClassicBorderDecorator ContentPresenter 在可视化树中获取和对象。 如果尚未优化模板控件,则要在可视化树中创建大量不必要的额外对象。 有关可视化树的详细信息,请参见 WPF 图形呈现概述。
延迟滚动
默认情况下,用户拖动滚动条上的滚动块时,内容视图会不断更新。 如果控件中滚动较慢,请考虑使用延迟滚动。 在延迟滚动中,仅在用户释放滚动块时才会更新内容。
若要实现延迟滚动,请将 IsDeferredScrollingEnabled 属性设置为 true
。 IsDeferredScrollingEnabled 是附加属性,可在 ScrollViewer ScrollViewer 其控件模板中设置的任何控件上进行设置。
实现性能功能的控件
下表列出了显示数据的常见控件及其性能功能支持。 有关如何启用这些功能的信息,请参阅先前章节。
控件 | 虚拟化 | 容器回收 | 延迟滚动 |
---|---|---|---|
ComboBox | 可启用 | 可启用 | 可启用 |
ContextMenu | 可启用 | 可启用 | 可启用 |
DocumentViewer | 不可用 | 不可用 | 可启用 |
ListBox | 默认 | 可启用 | 可启用 |
ListView | 默认 | 可启用 | 可启用 |
TreeView | 可启用 | 可启用 | 可启用 |
ToolBar | 不可用 | 不可用 | 可启用 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧