When you want to make an object binding-aware you have two choices : implements INotifyPropertyChanged or creates DependencyProperties. Which one is the best ? Let's try to answer this question !How to implement INotifyPropertyChangedDeclaring that your class is implementing INotifyPropertyChang

Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please clickhere to have a confirmation email sent so we can confirm your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

When you want to make an object binding-aware you have two choices : implementINotifyPropertyChanged or create DependencyProperties. Which one is the best? Let's try to answer this question!

How to Implement INotifyPropertyChanged

Declaring that your class is implementing INotifyPropertyChanged adds anPropertyChangedEventHandler that you raise for every changes of the properties. We also add a little tricky method checkIfPropertyNameExists(String propertyName) which checks by reflection when debugging if the property name really exists! You usually ends up with code like this :

Copy Code

  1. /// <summary>
  2. /// Base class for all my viewModel.
  3. /// </summary>
  4. public class ViewModelBase : INotifyPropertyChanged
  5. {
  6. #region INotifyPropertyChanged Members
  7. public event PropertyChangedEventHandler PropertyChanged;
  8. public void FirePropertyChanged(String propertyName)
  9. {
  10. checkIfPropertyNameExists(propertyName);
  11. PropertyChangedEventHandler handler = PropertyChanged;
  12. if (handler != null)
  13. handler.Invoke(this, new PropertyChangedEventArgs(propertyName));
  14. }
  15.  
  16. #endregion
  17.  
  18. [Conditional("DEBUG")]
  19. private void checkIfPropertyNameExists(String propertyName)
  20. {
  21. Type type = this.GetType();
  22. Debug.Assert(
  23. type.GetProperty(propertyName) != null,
  24. propertyName + "property does not exist on object of type : " + type.FullName);
  25. }
  26. }

As you can see, the code is quite easy to write and understand. You have to be very vigilant in checking the name of the property you gives as refactoring do not impacts Strings values but it stays quite simple.

DependencyProperties

MSDN definition of a DependencyProperty (link to) : a property that exists on aDependencyObject, is stored by the DependencyObject property store, and is identified by aDependencyProperty identifier on the owning DependencyObject.

Here is an example of how to create a DependencyProperty:

Copy Code

  1. public class MyDependencyObject : System.Windows.DependencyObject
  2. {
  3. public static readonly System.Windows.DependencyProperty MyDependencyPropertyProperty =
  4. System.Windows.DependencyProperty.Register("MyDependencyProperty", typeof(String), typeof(MyDependencyObject));
  5.  
  6. public String MyDependencyProperty
  7. {
  8. get { return (String)GetValue(MyDependencyObject.MyDependencyPropertyProperty); }
  9. set { SetValue(MyDependencyObject.MyDependencyPropertyProperty, value); }
  10. }
  11. }

Which one choose ?

Performances

All the tests are done under the .NET framework 4.0 with VisualStudio 2010 and .NET Memory Profiler 3.5. The tests were already done on this page MVVM – Lambda vs INotifyPropertyChanged vs DependencyObject but I do not get the same results...

Execution Times

To tests this I created a simple application and two textblocks binded to two String on my ViewModel. The tests were performed one by one and I took care to remove the inheritance of my ViewModel from DependencyObject when testing the INotifyPropertyChanged.

The code used to tests DependencyProperty is this one :

Copy Code

  1. public static readonly DependencyProperty StringWithDependencyPropertyProperty =
  2. DependencyProperty.Register("StringWithDependencyProperty", typeof(String), typeof(MainViewModel));
  3. public String StringWithDependencyProperty
  4. {
  5. get { return (String)GetValue(MainViewModel.StringWithDependencyPropertyProperty); }
  6. set { SetValue(MainViewModel.StringWithDependencyPropertyProperty, value); }
  7. }
  8. ...
  9. DateTime start = DateTime.Now;
  10. for (int i = 0; i < 100000; i++)
  11. _mainViewModel.StringWithDependencyProperty = i.ToString();
  12. DateTime end = DateTime.Now;
  13. Console.WriteLine("Total time for DependencyProperty : " + (end - start).TotalMilliseconds +" ms.");

The code used to tests INotifyPropertyChangedis this one :

Copy Code

  1. public String StringWithINotifyPropertyChanged
  2. {
  3. get { return _stringWithINotifyPropertyChanged; }
  4. set
  5. {
  6. _stringWithINotifyPropertyChanged = value;
  7. firePropertyChanged("StringWithINotifyPropertyChanged");
  8. }
  9. }
  10. ...
  11. DateTime start = DateTime.Now;
  12. for (int i = 0; i < 100000; i++)
  13. _mainViewModel.StringWithINotifyPropertyChanged = i.ToString();
  14. DateTime end = DateTime.Now;
  15. Console.WriteLine("Total time for INotifyPropertyChanged : " + (end - start).TotalMilliseconds+" ms.");

The results, for NO binding of the properties, were these :

Total time for DependencyProperty : 45 ms.

Total time for INotifyPropertyChanged : 171 ms.

The results, for one binding of the properties, were these :

Total time for DependencyProperty : 489 ms.

Total time for INotifyPropertyChanged : 1125 ms.

The results, for twelve binding of the properties, were these :

Total time for DependencyProperty : 3600ms.

Total time for INotifyPropertyChanged : 8375 ms.

DependencyProperty is 2,30 times faster than INotifyPropertyChanged for one binding and this number does not increase with the number of binded controls!

Edit : As argued in the comments and even if it is not the most common way to useINotifyPropertyChanged, I have made the tests with a static event args, and the results are :

Total time for no binding: 154ms.

Total time for one binding: 770ms.

Total time for twelve bindings: 5605ms.

DependencyProperies are still better, even if it's less...

Memory usage

I executed the same code and profiled the memory usages :

DependencyProperty created 600 new instances and add 44,583 bytesINotifyPropertyChanged created 876 new instances and add 63,536 bytes

DependencyProperty seems (in my tests) to create less instance and to use less memory than theINotifyPropertyChanged system...

Inheritance Issues

To create a DependencyProperty your objects needs to inherit from DependencyObject. This is not always possible and then using INotifyPropertyChanged is the only way to make it Bindable-aware.

Also, by being a DependencyObject, your object will carry with it all the dependency engine stuff and these limitations:

Inheritance from a base class you do not have a grip on ?=> No DependencyProperty !

Animations

Using DependencyProperty make the poperties animatable. If you want to animate a property, there is no simple work-around because, as the MSDN says : In order to be animated, the animation's target property must be a dependency property.

If you can't use DependencyProperty (when you do not create the objects for example), there is still work-arounds techniques.

Flexibility

Using INotifyPropertyChanged is sometimes more flexible than using DependencyProperty. Let me explain that. When you build a screen on which a lot of controls visibility dependsof some rules, you may declare a boolean which value is computed from other boolean.

For example, IsEditionPosible must be set to true only if IsAlreadyInEditionMode = falseand if UserHasEditionRights = true. So when changing the value ofIsAlreadyInEditionMode or UserHasEditionRights you must tells the binding engine thatIsEditionPosible has been updated too. It's easier to do this with INotifyPropertyChangedthan with the DependencyProperty with which you should have to create a method, which recalculate and reassign the new value to IsEditionPosible. Here you just have to use this little snippet :

Copy Code

  1. public Boolean IsAlreadyInEditionMode
  2. {
  3. get { return _isAlreadyInEditionMode ; }
  4. set
  5. {
  6. _isAlreadyInEditionMode = value;
  7. firePropertyChanged("IsAlreadyInEditionMode ");
  8. firePropertyChanged("IsEditionPosible");
  9. }
  10. }
  11.  
  12. public Boolean UserHasEditionRights
  13. {
  14. get { return _userHasEditionRights ; }
  15. set
  16. {
  17. _userHasEditionRights = value;
  18. firePropertyChanged("UserHasEditionRights");
  19. firePropertyChanged("IsEditionPosible");
  20. }
  21. }
  22.  
  23. public Boolean IsEditionPosible
  24. {
  25. get { return UserHasEditionRights && !IsAlreadyInEditionMode ; }
  26. }

Note that this is the way that I create computed value for easier binding in my viewModel but this is a subject where improvments may be done...

Flexibility (easier code writing) needed ?=> Choose INotifyPropertyChanged !

Testing

When you performs testing on your object, you will be in trouble if you use DependencyObject: the test are not done on the same thread that created the object and then throws you a "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it".

Testing => No DependencyProperty !

Code Readability/Writing

Some people argues that the use of DependencyProperties the code extremely ugly. I myself think that this is exaclty the same. To make easier the creation of dependencyProperty you can use this snippet : link to the snippet

DependencyProperties or INotifyPropertyChanged ?的更多相关文章

  1. 传智播客--数据绑定--INotifyPropertyChanged(小白内容)

    INotifyPropertyChanged一般在数据绑定的时候使用. InotifyPropertyChanged是.net内置的接口,数据绑定时会检测DataContext是否实现了Inotify ...

  2. INotifyPropertyChanged, Interface

    Data Object(class) impliment INotifyPropertyChanged; then the Object can update BindingSource. Impli ...

  3. Data Binding和INotifyPropertyChanged是如何协调工作的?

    前言 WPF的一大基础就是Data Binding.在基于MVVM架构的基础上,只有通过实现INotifyPropertyChanged接口的ViewModel才能够用于Data Binding. 要 ...

  4. 如何优雅的实现INotifyPropertyChanged接口

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ...

  5. INotifyPropertyChanged接口的PropertyChanged 事件

    INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知. 例如,考虑一个带有名为 FirstName 属性的 Person 对象. 若要提供 ...

  6. 为Page添加INotifyPropertyChanged功能

    在Page页面里面, DataContext 更新后,前台数据要求会自动更新. 但前台的绑定如果用x:bind 语法. 它要求强类型.直接关联到DataContext上就不行了. 需要为Page 添加 ...

  7. 【.NET深呼吸】INotifyPropertyChanged接口的真故事

    无论是在流氓腾的问问社区,还是在黑度贴吧,或是“厕所等你”论坛上,曾经看到过不少朋友讨论INotifyPropertyChanged接口.不少朋友认为该接口是为双向绑定而使用的,那么,真实的情况是这样 ...

  8. 使用CallerMemberName简化InotifyPropertyChanged的实现

    在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知,     class NotifyObject : INotifyPropertyChanged   ...

  9. C#-INotifyPropertyChanged(解决数据绑定的界面刷新问题)

    最近做项目用到DataGridView,用它绑定数据源后,如果数据源中的数据修改无法及时刷新到控件上,必须切换单元格的焦点才能导致刷新显示新数值,通过查官方文档,用INotifyPropertyCha ...

随机推荐

  1. poj1308(简单并查集)

    题目链接:http://poj.org/problem?id=1308 题意:x, y 表示x 与 y连接,给出一波这样的数据,问这组数据能否构成树,即不能形成回路,不能有多个根节点:要注意可以是空树 ...

  2. 瞧一瞧迷一般的SQLDA

    With static SQL, host variables used in embedded SQL statements are known at application compile tim ...

  3. codevs 2530大质数

    链接:http://codevs.cn/problem/1530/ 解题思路: 这个题最关键的剪枝还是 因子小于平方根,但不是像原来那样用. 逆转思维,与其说判断哪些是质数,不如说判断哪些不是质数,更 ...

  4. jq 确定删除方法与文件删除

    var choice=confirm("您确认要删除吗?", function() { }, null);                if(choice)           ...

  5. MySQL zabbix

    http://liqingbiao.blog.51cto.com/3044896/1712080

  6. PHP 获取图像信息 getimagesize 函数

    getimagesize() 函数用于获取图像尺寸,类型等信息. imagesx() 函数用于获取图像的宽度. imagesy() 函数用于获取图像的高度. getimagesize() getima ...

  7. 【C#】 用Route进行URL重写

    在.NET Framework 4中,微软推出了Route机制.这种机制不仅在MVC中大量运用,在WebForm中也可以使用. 和Contex.RewritePath()一样,Route功能也是写在G ...

  8. select count(*)和select count(1)哪个性能高

    select count(*).count(数字).count(字段名)在相同的条件下是没有性能差别的,一般我们在统计行数的时候都会把NULL值统计在内的,所以这样的话,最好就是使用COUNT(*) ...

  9. 【tornado】系列项目(一)之基于领域驱动模型架构设计的京东用户管理后台

    本博文将一步步揭秘京东等大型网站的领域驱动模型,致力于让读者完全掌握这种网络架构中的“高富帅”. 一.预备知识: 1.接口: python中并没有类似java等其它语言中的接口类型,但是python中 ...

  10. float 的有效数字为七位是怎么得出来的

    以下内容来自CSDN网友xian_wwq的回答(http://bbs.csdn.net/topics/390874239): float:   1bit(符号位) 8bits(指数位) 23bits( ...