闲话WPF之二六(WPF性能优化点)

在建立漂亮UI的同时,我们还需要关注应用程序的性能,WPF尤其如此。下面从MS的文档中总结出了一些有用的性能优化点。在实际编写的过程中,可以参考。这个Post非完全原创,是根据一些文档总结出来的。

1、建立逻辑树的时候,尽量考虑从父结点到子结点的顺序构建。因为当逻辑树的一个结点发生变化时(比如添加或删除),它的父结点和所有的子结点都会激发Invalidation。我们应该避免不必要的Invalidation。

2、当我们在列表(比如ListBox)显示了一个CLR对象列表(比如List)时,如果想在修改List对象后,ListBox也动态的反映这种变化。此时,我们应该使用动态的ObservableCollection对象绑定。而不是直接的更新ItemSource。两者的区别在于直接更新ItemSource会使WPF抛弃ListBox已有的所有数据,然后全部重新从List加载。而使用ObservableCollection可以避免这种先全部删除再重载的过程,效率更高。

3、在使用数据绑定的过程中,如果绑定的数据源是一个CLR对象,属性也是一个CLR属性,那么在绑定的时候对象CLR对象所实现的机制不同,绑定的效率也不同。

A、数据源是一个CLR对象,属性也是一个CLR属性。对象通过TypeDescriptor/PropertyChanged模式实现通知功能。此时绑定引擎用TypeDescriptor来反射源对象。效率最低。
B、数据源是一个CLR对象,属性也是一个CLR属性。对象通过INotifyPropertyChanged实现通知功能。此时绑定引擎直接反射源对象。效率稍微提高。
C、数据源是一个DependencyObject,而且属性是一个DependencyProperty。此时不需要反射,直接绑定。效率最高。

4、访问CLR对象和CLR属性的效率会比访问DependencyObject/DependencyProperty高。注意这里指的是访问,不要和前面的绑定混淆了。但是,把属性注册为DependencyProperty会有很多的优点:比如继承、数据绑定和Style。所以有时候我们可以在实现DependencyProperty的时候,利用缓存机制来加速访问速度:看下面的缓存例子:

public static readonly DependencyProperty MagicStringProperty =
    DependencyProperty.Register("MagicString", typeof(string), typeof(MyButton), new PropertyMetadata(new PropertyInvalidatedCallback(OnMagicStringPropertyInvalidated),new GetValueOverride(MagicStringGetValueCallback)));

 private static void OnMagicStringPropertyInvalidated(DependencyObject d)
  {
    // 将缓存的数据标识为无效
    ((MyButton)d)._magicStringValid = false;
  }

  private static object MagicStringGetValueCallback(DependencyObject d)
  {
    // 调用缓存的访问器来获取值
    return ((MyButton)d).MagicString;
  }

  // 私有的CLR访问器和本地缓存
  public string MagicString
  {
    get
    {
      // 在当前值无效时,获取最新的值保存起来
      if (!_magicStringValid)
      {
        _magicString = (string)GetValueBase(MagicStringProperty);
        _magicStringValid = true;
      }

      return _magicString;
    }
    set
    {
      SetValue(MagicStringProperty, value);
    }
  }

  private string _magicString;
  private bool _magicStringValid;

另外,因为注册的DependencyProperty在默认是不可继承的,如果需要继承特性,也会降低DependencyProperty值刷新的效率。注册DependencyProperty属性时,应该把DefaultValue传递给Register方法的参数来实现默认值的设置,而不是在构造函数中设置。

5、使用元素TextFlow和TextBlock时,如果不需要TextFlow的某些特性,就应该考虑使用TextBlock,因为它的效率更高。

6、在TextBlock中显式的使用Run命令比不使用Run命名的代码要高。

7、在TextFlow中使用UIElement(比如TextBlock)所需的代价要比使用TextElement(比如Run)的代价高。

8、把Label(标签)元素的ContentProperty和一个字符串(String)绑定的效率要比把字符串和TextBlock的Text属性绑定的效率低。因为Label在更新字符串是会丢弃原来的字符串,全部重新显示内容。

9、在TextBlock块使用HyperLinks时,把多个HyperLinks组合在一起效率会更高。看下面的两种写法,后一种效率高。

A、
<TextBlock Width="600" >
  <Hyperlink TextDecorations="None">MSN Home</Hyperlink>
</TextBlock>
<TextBlock Width="600" >
  <Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>

B、
<TextBlock Width="600" >
  <Hyperlink TextDecorations="None">MSN Home</Hyperlink>
  <Hyperlink TextDecorations="None">My MSN</Hyperlink>
</TextBlock>

10、任与上面TextDecorations有关,显示超链接的时候,尽量只在IsMouseOver为True的时候显示下划线,一直显示下划线的代码高很多。

11、在自定义控件,尽量不要在控件的ResourceDictionary定义资源,而应该放在Window或者Application级。因为放在控件中会使每个实例都保留一份资源的拷贝。

12、如果多个元素使用相同的Brush时,应该考虑在资源定义Brush,让他们共享一个Brush实例。

13、如果需要修改元素的Opacity属性,最后修改一个Brush的属性,然后用这个Brush来填充元素。因为直接修改元素的Opacity会迫使系统创建一个临时的Surface。

14、在系统中使用大型的3D Surface时,如果不需要Surface的HitTest功能,请关闭它。因为默认的HitTest会占用大量的CPU时间进行计算。UIElement有应该IsHitTestVisible属性可以用来关闭HitTest功能。

posted @ 2007-01-19 13:33 Yiling Lai 阅读(3102) 评论(12)  编辑 收藏 网摘 所属分类: WPF

  回复  引用  查看    
#1楼 2007-01-20 14:36 | stswordman      
好!
YILing 原文在哪里啊?
谢谢
  回复  引用    
#2楼 2007-01-21 11:35 | Yiling Lai[匿名] [未注册用户]
@ stswordman

WPF的性能文档白皮书和SDK
  回复  引用    
#3楼 2007-01-25 16:01 | 个人知识空间 [未注册用户]
现在好象很难找到较完整的教程啊
  回复  引用  查看    
#4楼 [楼主]2007-01-25 17:16 | Yiling Lai      
@个人知识空间

确实,现在中文的资料很少
  回复  引用    
#5楼 2007-04-12 23:09 | 桂素伟 [未注册用户]
一口气看完版主的这二十多篇Blog,收获了不少东西,在这里谢谢了!期待新的内容!
  回复  引用  查看    
#6楼 [楼主]2007-04-13 08:36 | Yiling Lai      
@桂素伟

谢谢,最近比较忙,更新很少!
  回复  引用    
#7楼 2007-04-28 10:18 | winnerzone [未注册用户]
谢谢楼主了.就在找性能优化的文章呢
  回复  引用    
#8楼 2008-01-16 18:13 | 清新的风 [未注册用户]
不错,楼主,期待更新
  回复  引用    
#9楼 2008-02-27 11:26 | 阿慧2008 [未注册用户]
Waiting……
  回复  引用  查看    
#10楼 2008-09-07 10:08 | 大侠赵敏      
博主兄你好,小弟现在下大学习WPF,现在学习过程中有好些问题不是清楚,请可以告诉我你的MSN及邮箱吗?谢谢 (我的MSN:zhoujiguo1985@live.cn, email:zhoujiguo1985@163.com)
  回复  引用    
#11楼 2008-11-04 19:33 | tongxl [未注册用户]
对老兄的学习能力,wpf。

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:

相关链接: