细数改善WPF应用程序性能的10大方法

简介: 原文:细数改善WPF应用程序性能的10大方法      WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密,给用户的感觉是它太吃资源了,WPF程序的性能和硬件确实有很大的关系,越高档的机器性能越有优势。
原文: 细数改善WPF应用程序性能的10大方法

      WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密,给用户的感觉是它太吃资源了,WPF程序的性能和硬件确实有很大的关系,越高档的机器性能越有优势。

      程序性能改善不是一蹴而就的,好的设计可以消除影响性能的问题,例如,在运行时构造对象就会对程序的性能造成影响。虽然WPF通过增强的导航等功能提供了更丰富的用户界面,但你应该考虑你的用户是否的确需要富图形界面,尽管WPF有这样那样的问题,但在UI设计,特别是自定义风格和控件模板方面,的确给开发人员提供了不少灵活性。

      渲染WPF程序的主要因素是它包含的像素量,WPF使用微软的DirectX在程序运行的硬件上进行渲染,因此,如果你的机器有独立显卡,运行WPF程序会更流畅。除了提高硬件配置外,我们来看看10个提高WPF程序性能的软方法。

      1、降低Bitmapscalingmode,加速图像渲染

      当你的WPF程序中包含有动画时,你可以使用RenderOptions对象的BitmapScalingMode属性降低资源消耗,需要将BitMapScalingMode属性的值设为LowQuality,这样就会使用加速算法处理图像,而不是默认的高质量图像重采样算法。下面的代码片段显示了最基本的实现方法:

RenderOptions.SetBitmapScalingMode(imageObject,BitmapScalingMode.LowQuality);

      2、在正确的地方使用正确的元素

      我们需要在正确的地方使用正确的元素,当你生成树时应避免使用UIElements作为子或嵌套控件,最好的例子是FlowDocument,我们经常在FlowDocument中使用TextBlock元素。

<FlowDocument>
    <Paragraph>
      <TextBlock>some text</TextBlock>
    </Paragraph>
  </FlowDocument>

      除了上面这样写外,我们还可以象下面这样重写XAML内容,Run元素不是UIElement,渲染时系统开销更小。

<FlowDocument><Paragraph><Run>some text</Run></Paragraph></FlowDocument>

      类似的例子是使用Label控件的Content属性,如果在其生命周期内内容不止更新一次,并且是个字符串,这个数据绑定过程可能会阻碍程序的性能,由于内容是一个字符串,在数据绑定期间它会被丢弃,并重新创建。在这种情况下使用TextBlock将数据绑定到Text属性更有效。

      在可视化树中出现不必要的元素也会降低WPF程序的速度,你最好结合布局优化默认的控件模板。

      3、增加静态资源的使用

      静态资源是预定义的资源,可以连接到XAML属性,它类似于编译时绑定,不会影响性能,另一方面,动态资源涉及到运行时查找和对象的构建,从而会影响到性能。但也需要注意,静态资源需要在编译时展示。

      静态资源的引用可以参考下面的方法:

<Button 
        Template="{StaticResource RoundButtonWithThickEdge}"
        x:Name="button1" Content="Button 1" >
</Button>

      下面的代码片段显示了静态资源RoundButtonWithThickEdge的定义:

<ControlTemplate 
       x:Key="RoundButtonWithThickEdge" 
       TargetType="{x:Type Button}">
       <Grid>
         <Ellipse Fill="{TemplateBinding Background}" 
           Stroke="{x:Null}" 
           HorizontalAlignment="Stretch" x:Name="ellipse"/>
             <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                 <Ellipse Stroke="{x:Null}" Margin="2,3,4,5">
                   <Ellipse.Fill>
                     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                   <GradientStop Color="#FFFBFAFA" Offset="0"/>
                  <GradientStop Color="#1DFFFFFF" Offset="1"/>
             </LinearGradientBrush>
           </Ellipse.Fill>
         </Ellipse>
       </Grid>
</ControlTemplate>

      4、当你想显示大型数据时,使用UI虚拟化的控件

      想象一下一个组合框绑定大量行时的样子,它会让组合框中项目的展现变得非常慢,这是因为在这种情况下,程序需要计算每个项目的具体显示位置,使用WPF时,你可以延迟这个行为,这就叫做UI虚拟化,它只会在其可见范围内生产项目显示需要的容器。

      要实现这种效果,你需要将相应控件的IsVirtualizing属性设为True,例如,Listbox经常用来绑定大型数据集,它是UI虚拟化的重要候选者,其它适宜UI虚拟化的控件包括ComboboxListViewTreeView

      5、使用延迟滚动增强用户体验

      如果你还记得可滚动的DataGridListBox,它们往往会降低整个应用程序的性能,因为在滚动时会强制连续更新,这是默认的行为,在这种情况下,我们可以使用控件的延迟滚动(Deferred Scrolling)属性增强用户体验。你需要做的仅仅是将IsDeferredScrollingEnabled附加属性设为True

      6、使用字体缓存服务提高启动时间

      WPF应用程序之间可以共享字体数据,它是通过一个叫做PresentationFontCache ServiceWindows服务实现的,它会随Windows自动启动。

  你可以在控制面板的“服务”中找到这个服务(或在“运行”框中输入Services.msc),确保这个服务已经启动。

      7、使用卸载事件卸载不必要的动画

      动画肯定会占用一定的资源,如果处置方式不当,将会消耗更多的资源,如果你认为它们无用时,你应该考虑如何处理他们,如果不这样做,就要等到可爱的垃圾回收器先生来回收资源。

  例如,假设要删除一个StoryBorad,在Unload事件中使用StoryBoradRemove方法,下面的例子来自MSDN

<EventTrigger RoutedEvent="Page.Unloaded" >
          <EventTrigger.Actions>
            <RemoveStoryboard BeginStoryboardName="myBeginStoryboard" />
          </EventTrigger.Actions>
  </EventTrigger>

      8、使用容器回收提高性能

      你可以通过回收执行虚拟化的容器来提高性能,下面的代码片段将ViruatlizationMode设为Recycling,它让你可以获得更好的性能。当用户滚动或抵达另一个项目时,它强制重复使用容器对象。

settingVirtualizingStackPanel.VirtualizationMode="Recycling"

      9、预测图像绘制能力

      使用RenderCapability.Tier属性确定机器是支持硬件加速,还是部分硬件加速,疑惑没有硬件加速,下面的代码显示了你要如何检查Tier

int displayTier = (System.Windows.Media.RenderCapability.Tier > 16)
  
  if (displayTier == 0)
  {
     //no hardware acceleration
  }
  else if (displayTier == 1)
  {
     //partial hardware acceleration
  }
  else
  {
     //supports hardware acceleration
  }

      确定了之后,你就可以有选择性地选择那些在用户硬件上工作得很好的功能

      10、使用WPF分析工具分析WPF程序

      分析WPF程序是理解其行为很重要的一步,市场上有大量现成的WPF程序分析工具,如SnoopWPFPerfPerforatorVisual Profiler,其中PerforatorVisual ProfilerWPF Performance Suite的一部分,要了解这些工具的用法,请去它们的项目主页。

目录
相关文章
|
缓存 C# 虚拟化
WPF列表性能提高技术
WPF数据绑定系统不仅需要绑定功能,还需要能够处理大量数据而不会降低显示速度和消耗大量内存,WPF提供了相关的控件以提高性能,所有继承自`ItemsControl`的控件都支持该技术。
194 0
|
5月前
|
C# 开发者 Windows
WPF 应用程序开发:一分钟入门
本文介绍 Windows Presentation Foundation (WPF),这是一种用于构建高质量、可缩放的 Windows 桌面应用程序的框架,支持 XAML 语言,方便 UI 设计与逻辑分离。文章涵盖 WPF 基础概念、代码示例,并深入探讨常见问题及解决方案,包括数据绑定、控件样式与模板、布局管理等方面,帮助开发者高效掌握 WPF 开发技巧。
202 65
|
6月前
|
前端开发 C# 开发者
WPF开发者必读:MVVM模式实战,轻松构建可维护的应用程序,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离关注点,提高了代码的可维护性和可扩展性。本文详细介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定与逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种模式,开发者可以更高效地构建桌面应用程序。希望本文能帮助你在WPF开发中更好地应用MVVM模式。
339 1
|
6月前
|
C# 微服务 Windows
模块化革命:揭秘WPF与微服务架构的完美融合——从单一职责原则到事件聚合器模式,构建高度解耦与可扩展的应用程序
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中借鉴微服务架构思想,实现模块化设计。通过将WPF应用分解为独立的功能模块,并利用事件聚合器实现模块间解耦通信,可以有效提升开发效率和系统可维护性。文中还提供了具体示例代码,展示了如何使用事件聚合器进行模块间通信,以及如何利用依赖注入进一步提高模块解耦程度。此方法不仅有助于简化复杂度,还能使应用更加灵活易扩展。
140 0
|
6月前
|
测试技术 C# 开发者
“代码守护者:详解WPF开发中的单元测试策略与实践——从选择测试框架到编写模拟对象,全方位保障你的应用程序质量”
【8月更文挑战第31天】单元测试是确保软件质量的关键实践,尤其在复杂的WPF应用中更为重要。通过为每个小模块编写独立测试用例,可以验证代码的功能正确性并在早期发现错误。本文将介绍如何在WPF项目中引入单元测试,并通过具体示例演示其实施过程。首先选择合适的测试框架如NUnit或xUnit.net,并利用Moq模拟框架隔离外部依赖。接着,通过一个简单的WPF应用程序示例,展示如何模拟`IUserRepository`接口并验证`MainViewModel`加载用户数据的正确性。这有助于确保代码质量和未来的重构与扩展。
169 0
|
6月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
523 0
|
6月前
|
开发者 C# 自然语言处理
WPF开发者必读:掌握多语言应用程序开发秘籍,带你玩转WPF国际化支持!
【8月更文挑战第31天】随着全球化的加速,开发多语言应用程序成为趋势。WPF作为一种强大的图形界面技术,提供了优秀的国际化支持,包括资源文件存储、本地化处理及用户界面元素本地化。本文将介绍WPF国际化的实现方法,通过示例代码展示如何创建和绑定资源文件,并设置应用程序语言环境,帮助开发者轻松实现多语言应用开发,满足不同地区用户的需求。
118 0
|
6月前
|
开发者 C# UED
WPF多窗口应用程序开发秘籍:掌握窗口创建、通信与管理技巧,轻松实现高效多窗口协作!
【8月更文挑战第31天】在WPF应用开发中,多窗口设计能显著提升用户体验与工作效率。本文详述了创建新窗口的多种方法,包括直接实例化`Window`类、利用`Application.Current.MainWindow`及自定义方法。针对窗口间通信,介绍了`Messenger`类、`DataContext`共享及`Application`类的应用。此外,还探讨了布局控件与窗口管理技术,如`StackPanel`与`DockPanel`的使用,并提供了示例代码展示如何结合`Messenger`类实现窗口间的消息传递。总结了多窗口应用的设计要点,为开发者提供了实用指南。
374 0
|
6月前
|
C# 前端开发 UED
WPF数据验证实战:内置控件与自定义规则,带你玩转前端数据验证,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用开发中,数据验证是确保输入正确性的关键环节。前端验证能及时发现错误,提升用户体验和程序可靠性。本文对比了几种常用的WPF数据验证方法,并通过示例展示了如何使用内置验证控件(如`TextBox`)及自定义验证规则实现有效验证。内置控件结合`Validation`类可快速实现简单验证;自定义规则则提供了更灵活的复杂逻辑支持。希望本文能帮助开发者更好地进行WPF数据验证。
209 0
|
6月前
|
开发者 C# Windows
WPF布局大揭秘:掌握布局技巧,轻松创建响应式用户界面,让你的应用程序更上一层楼!
【8月更文挑战第31天】在现代软件开发中,响应式用户界面至关重要。WPF(Windows Presentation Foundation)作为.NET框架的一部分,提供了丰富的布局控件和机制,便于创建可自动调整的UI。本文介绍WPF布局的基础概念与实现方法,包括`StackPanel`、`DockPanel`、`Grid`等控件的使用,并通过示例代码展示如何构建响应式布局。了解这些技巧有助于开发者优化用户体验,适应不同设备和屏幕尺寸。
192 0