WPF 性能 UI 虚拟化 软件开发人员的思考

UI 虚拟化是 WPF 采用的一项技术,框架会仅创建用户可见的 UI 元素。例如,如果 ListView 中有 1000 个文本块控件,但您只能查看其中的 10 个,那么 VisualTree 中也只会显示 10 个文本块。向下滚动时,不再可见的元素将被丢弃,并创建下一组可见项。这种虚拟化技术在速度和内存方面都带来了显著的 UI 性能优势。

WPF 中的 UI 虚拟化由 VirtualizingStackPanel 提供,并且默认启用。您可以像图中所示,在 StackPanel 上显式指定 UI 虚拟化的开启/关闭。

<StackPanel VirtualizingStackPanel.IsVirtualizing="True"></StackPanel>

请注意,UI 虚拟化仅在 ItemsControl 生成其自身模板时才有效。如果生成了模板,然后添加虚拟化,则虚拟化将被禁用。因此,UI 虚拟化的缺点在于它在某些情况下是禁用的。其中一种情况是您覆盖 ItemsPanelTemplate 或 ItemsControl 的模板。在这种情况下,如果 ItemsPanelTemplate 由开发人员自定义,则 UI 虚拟化将被禁用。因此,如果您的 ItemsControl 显示已加载的数据,那么您就有麻烦了。为了避免这种情况并在覆盖 ItemsPanelTemplate 的情况下启用 UI 虚拟化,我们需要使用 VirtualizingStackPanel。

为了测试启用和禁用虚拟化的效果,我编写了一个简单的应用程序。它有一个列表视图,其 itempanel 模板已自定义 - 首先使用普通的 StackPanel,然后使用 VirtualizingStackPanel。它从名称列表中加载文本块。

当我在列表中运行包含 1000000 个项目的测试时,在没有虚拟化的情况下,程序根本无法启动。它占用了近 2 GB 的内存,而且根本无法运行。所以我不得不终止它。然后,启用虚拟化后,程序很快就启动了,内存占用只有 200MB。在此之前,让我们先看看我使用的 XAML 和后台代码。它还会向您展示如何自定义 ItemsPanelTemplate 和使用 VirtualizingStackPanel。

<Window x:Class="NiceControlsTest.Window2"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Window2"Height="300"Width="300"Loaded="Window_Loaded">

<Grid>

<ListView ItemsSource="{BindingNames}"Name="lv">

<ListView.ItemsPanel>

<ItemsPanelTemplate>

<!--<StackPanel/>

如果使用 StackPanel,则消耗的内存将超过 2GB,并且速度非常慢。

-->

<VirtualizingStackPanel>

<!--内存占用仅 200 mb-->

</VirtualizingStackPanel>

</ItemsPanelTemplate>

</ListView.ItemsPanel>

<ListView.ItemTemplate>

<DataTemplate>

<TextBlock Text="{Binding}"/>

</DataTemplate>

</ListView.ItemTemplate>

</ListView>

</Grid>

</Window>

背后的代码非常简单:

public partial class Window2 : Window

{

public List<string> Names { get; set; }

private DateTime start;

public Window2()

{

start = DateTime.Now;

InitializeComponent();

Names = new List<string>();

for (int i = 0; i < 10000; i++)

Names.Add("Name : " + i);

lv.DataContext = this;

}

private void Window_Loaded(object sender, RoutedEventArgs e)

{

MessageBox.Show((DateTime.Now - start).TotalSeconds.ToString());

}

}

经过精确测量了从窗口构建到加载的时间。结果发现,仅使用 StackPanel 时,对于使用的 10000 个项目(为了加快测量速度,减少了项目数量),内存占用约为 176 MB,启动时间为 7 到 10 秒。而使用 VirtualizingStackPanel 时,内存占用略高于 16 MB,启动时间为 0.3 到 0.8 秒。

个人认为这对我们开发人员来说非常有利。我们可以设计和开发大型高负载图形应用程序,而无需担心进行某种程度的优化。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
lingxiao1688810 小时前
WebApi详解+Unity注入--下篇:Unity注入
unity·c#·wpf
lowhot18 小时前
C语言UI框架
c语言·开发语言·笔记·ui
William_cl19 小时前
ASP.NET Core 视图组件:从入门到避坑,UI 复用的终极方案
后端·ui·asp.net
初级代码游戏20 小时前
云存储的删除设计
ui·删除·交互设计·onedrive·icloud·界面设计
Kang.Charles21 小时前
Lua UI系统框架逻辑详解
ui·lua
Sahadev_21 小时前
从逻辑表达式到原子化构建:复杂 UI 组件的重构之道
ui·重构
无心水21 小时前
【分布式利器:腾讯TSF】6、TSF可观测性体系建设实战:Java全链路Metrics+Tracing+Logging落地
java·分布式·架构·wpf·分布式利器·腾讯tsf·分布式利器:腾讯tsf
示申○言舌21 小时前
Unity高性能参数差异化URP Shader圆角圆环UI进度条
ui·unity·游戏引擎·圆环进度条·参数差异化·材质参数独立·圆角圆环
zhengxianyi5151 天前
yudao-ui-go-view路由同时支持history及hash
ui·golang·哈希算法
故事不长丨1 天前
C#字典(Dictionary)全面解析:从基础用法到实战优化
开发语言·c#·wpf·哈希算法·字典·dictionary·键值对