惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Check Point Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Secure Thoughts
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
The Blog of Author Tim Ferriss
B
Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Google DeepMind News
Google DeepMind News
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
Arctic Wolf
T
The Exploit Database - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
AWS News Blog
AWS News Blog
MongoDB | Blog
MongoDB | Blog
Y
Y Combinator Blog
Google Online Security Blog
Google Online Security Blog
T
Troy Hunt's Blog
I
InfoQ
L
LINUX DO - 热门话题
WordPress大学
WordPress大学
C
Cisco Blogs
G
GRAHAM CLULEY
The Register - Security
The Register - Security
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Schneier on Security
Schneier on Security
Project Zero
Project Zero
H
Hackread – Cybersecurity News, Data Breaches, AI and More
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
H
Hacker News: Front Page
小众软件
小众软件
雷峰网
雷峰网
The Hacker News
The Hacker News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
Tor Project blog
博客园 - 聂微东
N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
The GitHub Blog
The GitHub Blog
腾讯CDC
P
Palo Alto Networks Blog
Scott Helme
Scott Helme

博客园 - zhaotianff

解决IIS服务器typecho上传附件后无法访问的问题 Visual Studio编译过程中拷贝文件的一些实用小技巧 Jenkins快速入门教程 .NET是什么?为什么要选择.NET? 如何在WPF中实现类似DevOps的自动化流程 一文带你搞懂医疗器械设计开发全生命周期 Windows如何清除本机记录的git用户名和密码 HL7协议详解 医疗行业 GDT 数据格式详解 一文带你搞懂C# 异步编程(async/await)底层原理 如何在C#中使用Chromium headless(无头模式)浏览器 不同.NET版本中的WPF新增功能 如何在WPF中使用 Fluent 主题 Windows平台下的各种原生UI框架介绍 C#如何Hook托管函数 WinDbg 用户层调试进阶教程 Windows编程的一些基础理论 推荐一款优秀的Windows经典文件管理器项目-WinFile Windows如何阻止应用程序联网 如何在WPF中捕获窗口外的事件 如何查看Windows进程的启动来源 Visual Studio 2026新解决方案格式slnx详解 我的微软MVP申请通过了 WPF MVVM实战系列教程(八、Prism DialogService, 对话框服务) WPF MVVM实战系列教程(七、Prism模块化) WPF MVVM实战系列教程(六、Prism区域导航) WPF MVVM实战系列教程(五、Prism中的MVVM) WPF MVVM实战系列教程(四、Prism中的依赖注入) 微软 IDE 新纪元:Visual Studio 2026 初体验 Windows 7无法安装VMWare Tools的解决办法 WPF MVVM实战系列教程(三、创建Bootstrapper/启动器) WPF MVVM实战系列教程(二、使用Visual Studio 创建Prism项目) WPF MVVM实战系列教程(一、Prism框架介绍)
WPF 性能优化实战指南
zhaotianff · 2026-01-22 · via 博客园 - zhaotianff

根据呈现层动态设置渲染内容

WPF的底层是使用Microsoft DirectX进行渲染的,WPF会判断软硬件环境来决定使用软件渲染管道还是硬件渲染管道。

这里涉及一个概念叫呈现层

我们可以通过下面这种方式来查看呈现层

1 RenderCapability.Tier >> 16
返回值呈现层说明
0x00000000 0 设备上没有可用于应用程序的图形硬件加速。 所有图形功能都使用软件加速。 DirectX 版本级别低于版本 9.0。
0x00010000 1 如果必要的系统资源可用且尚未耗尽,WPF 的大部分图形功能将使用硬件加速。 这对应于大于或等于 9.0 的 DirectX 版本。
0x00020000 2 WPF 的大部分图形功能将使用硬件加速,前提是必要的系统资源尚未耗尽。 这对应于大于或等于 9.0 的 DirectX 版本。

呈现层 1 和呈现层 2 的图形硬件需求差异:

Feature第 1 层第 2 层
DirectX 版本 必须高于或等于 9.0。 必须高于或等于 9.0。
视频 RAM 必须大于或等于 60 MB。 必须大于或等于 120 MB。
像素着色器 版本级别必须高于或等于 2.0。 版本级别必须高于或等于 2.0。
顶点着色器 没有要求。 版本级别必须高于或等于 2.0。
多纹理单元 没有要求。 单元数必须大于或等于 4。

就现阶段硬件而言,大部分WPF应用是使用呈现层2进行渲染。但是也不排除会有一些老硬件仍在运行WPF应用程序。

这里我们可以做一些判断,针对老机器做一些适配以提高性能

假设我们有一个ListBox,里面显示一些文本和图片。

当呈现层是0或者1的时候,只显示文本。呈现层是2的时候,显示文本和图片

1、首先定义数据模型

1 public class Model
2 {
3     public string Content { get; set; }
4 
5     public string Image { get; set; }
6 }

2、定义不同呈现层的数据模板

 1 <Window.Resources>
 2     <DataTemplate x:Key="SimpleTemplate">
 3         <TextBlock Text="{Binding Content}"></TextBlock>
 4     </DataTemplate>
 5 
 6     <DataTemplate x:Key="FullTemplate">
 7         <Grid Height="300">
 8             <Grid.RowDefinitions>
 9                 <RowDefinition/>
10                 <RowDefinition Height="30"/>
11             </Grid.RowDefinitions>
12 
13             <Image Source="{Binding Image}"></Image>
14             <TextBlock Text="{Binding Content}" HorizontalAlignment="Center" Grid.Row="1"></TextBlock>
15         </Grid>
16     </DataTemplate>
17 </Window.Resources>

3、在界面上增加一个ListBox控件

1  <Grid>
2      <ListBox Name="list"></ListBox>
3  </Grid>

4、使用模板选择器根据呈现层动态切换数据模板

 1  public class MyDataTemplateSelector : DataTemplateSelector
 2  {
 3      public override DataTemplate
 4          SelectTemplate(object item, DependencyObject container)
 5      {
 6          switch (MainWindow.RenderTier)
 7          {
 8              case 0:
 9              case 1:
10                  return Application.Current.MainWindow.FindResource("FullTemplate") as DataTemplate;
11              case 2:
12                  return Application.Current.MainWindow.FindResource("SimpleTemplate") as DataTemplate;
13          }
14 
15          return null;
16      }
17  }

这里用到了模板选择器功能,可以参考前面的文章

https://www.cnblogs.com/zhaotianff/p/18380995

5、增加一些测试数据并绑定到列表上就可以看到效果

 1  public MainWindow()
 2  {
 3      InitializeComponent();
 4 
 5 
 6      models.Add(new Model() {Content = "image 1",Image = "1.jpg" });
 7      models.Add(new Model() { Content = "image 2", Image = "2.jpg" });
 8      models.Add(new Model() { Content = "image 3", Image = "3.jpg" });
 9 
10      this.list.ItemsSource = models;
11      this.list.ItemTemplateSelector = new MyDataTemplateSelector();
12  }

image

呈现层0/1运行效果

image

 呈现层2运行效果

优化资源使用

1、尽量使用StaticResource来查找资源而不是DynamicResource

  • StaticResource(静态资源):在加载 XAML 时一次性解析并绑定资源,之后资源的修改不会反映到引用处。可以理解为 “编译时绑定”。
  • DynamicResource(动态资源):在运行时延迟解析资源,并且当资源本身发生变化时,引用处会自动更新。可以理解为 “运行时绑定”。而且每当请求资源时,无论资源是否已更改,DynamicResource都会重复查找资源的值


我们可以通过一个示例来看一下

首先我们定义一个资源在App.xaml中

 1 <Application x:Class="WpfApp24.App"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:local="clr-namespace:WpfApp24"
 5              xmlns:sys="clr-namespace:System;assembly=mscorlib"
 6              StartupUri="MainWindow.xaml">
 7     <Application.Resources>
 8         <ResourceDictionary>
 9             <sys:String x:Key="Res">HelloWorld</sys:String>
10         </ResourceDictionary>
11     </Application.Resources>
12 </Application>

然后在界面上放置两个Label,并且绑定到这个资源。再放置一个按钮,用于修改资源

1  <StackPanel>
2      <Label Content="{StaticResource Res}"></Label>
3      <Label Content="{DynamicResource Res}"></Label>
4      <Button Content="修改资源" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"></Button>
5  </StackPanel>

当我们点击按钮时,修改资源

1  private void Button_Click(object sender, RoutedEventArgs e)
2  {
3      Application.Current.Resources["Res"] = "HelloWorld 修改";
4  }

运行效果

demo

2、尽量不要定义内联资源

尽可能的重用资源,也就是将资源定义到资源字典中,并放到App.xaml中。

一般来说,我们已经习惯这样去做了。不要为了图方便,定义内联资源,这样不仅增加了维护的难度,也会降低程序性能。