Getting Deep into .net

December 12, 2012

Implementing INotifyPropertyChanged in C#5.0 way

Filed under: .NET,How To,Linq — goldytech @ 11:54 am
Tags:

 

All XAML developers are well aware of INotifyPropertyChanged interface. This interface is key to the data binding. Every ViewModel class or ViewModelBase abstract class implements this interface. One of the biggest issue with it is that the PropertyChangedEventHandler delegate event argument, PropertyChangedEventArgs constructor accepts the property name as string value. This can introduce bug in your code because of “MAGIC STRINGS” , where by which if developer misspell the property name or you require to rename your property , then it should be done very carefully otherwise your data binding can go completely for a toss and you would go in circles to figure out what the issue is. Let me illustrate what I am talking about with the code snippet below.

Old way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         private string customerNameValue = String.Empty;
  4.         private string phoneNumberValue = String.Empty;
  5.  
  6.         public event PropertyChangedEventHandler PropertyChanged;
  7.  
  8.         private void NotifyPropertyChanged(String propertyName)
  9.         {
  10.             if (PropertyChanged != null)
  11.             {
  12.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  13.             }
  14.         }
  15.  
  16.         public string CustomerName
  17.         {
  18.             get
  19.             {
  20.                 return this.customerNameValue;
  21.             }
  22.  
  23.             set
  24.             {
  25.                 if (value != this.customerNameValue)
  26.                 {
  27.                     this.customerNameValue = value;
  28.                     NotifyPropertyChanged("CustomerName"); //Magic strings
  29.                 }
  30.             }
  31.         }
  32.  
  33.         public string PhoneNumber
  34.         {
  35.             get
  36.             {
  37.                 return this.phoneNumberValue;
  38.             }
  39.  
  40.             set
  41.             {
  42.                 if (value != this.phoneNumberValue)
  43.                 {
  44.                     this.phoneNumberValue = value;
  45.                     NotifyPropertyChanged("PhoneNumber"); //Magic strings
  46.                 }
  47.             }
  48.         }
  49.     }

In this short post I will talk about how you can avoid using these magic strings by using one of C# new 5.0 feature named as CallerMemberName attribute with support of optional parameters. So let us do some code refactoring in the above code and remove these magic strings. Have a look at the code snippet below.

New way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         // These fields hold the values for the public properties.
  4.         private string customerNameValue = String.Empty;
  5.         private string phoneNumberValue = String.Empty;
  6.  
  7.         public event PropertyChangedEventHandler PropertyChanged;
  8.  
  9.         private void NotifyPropertyChanged([CallerMemberName]
  10.                                            String propertyName = "")
  11.         {
  12.             if (PropertyChanged != null)
  13.             {
  14.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  15.             }
  16.         }
  17.  
  18.         public string CustomerName
  19.         {
  20.             get
  21.             {
  22.                 return this.customerNameValue;
  23.             }
  24.  
  25.             set
  26.             {
  27.                 if (value != this.customerNameValue)
  28.                 {
  29.                     this.customerNameValue = value;
  30.                     NotifyPropertyChanged(); //Look ma no magic strings
  31.                 }
  32.             }
  33.         }
  34.  
  35.         public string PhoneNumber
  36.         {
  37.             get
  38.             {
  39.                 return this.phoneNumberValue;
  40.             }
  41.  
  42.             set
  43.             {
  44.                 if (value != this.phoneNumberValue)
  45.                 {
  46.                     this.phoneNumberValue = value;
  47.                     NotifyPropertyChanged(); //Look ma no magic strings
  48.                 }
  49.             }
  50.         }
  51.     }

Just have a look at NotifyPropertyChanged method in the above code snippet. This method argument is decorated with CallerMemberName attribute. This will replace the property name in the set accessor of that property. So you don’t need to hardcode any property name.

On the closing note I would also like to say that this is not the only way you can avoid the MAGIC STRINGS in the method name. If you are fan of functional programming like me ;) and have some knowledge of generics you can use Linq Expressions to achieve the same. Let us see one more code snippet which does this.

Smart way implementation
  1. public class CustomerViewModel : INotifyPropertyChanged
  2.     {
  3.         // These fields hold the values for the public properties.
  4.         private string customerNameValue = String.Empty;
  5.         private string phoneNumberValue = String.Empty;
  6.  
  7.         public event PropertyChangedEventHandler PropertyChanged;
  8.  
  9.         private void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
  10.         {
  11.             var lambda = (LambdaExpression)expression;
  12.             MemberExpression memberExpr;
  13.             var body = lambda.Body as UnaryExpression;
  14.             if (body != null)
  15.             {
  16.                 var unaryExpr = body;
  17.                 memberExpr = (MemberExpression)unaryExpr.Operand;
  18.             }
  19.             else
  20.             {
  21.                 memberExpr = (MemberExpression)lambda.Body;
  22.             }
  23.             if (PropertyChanged != null)
  24.             {
  25.                 PropertyChanged(this, new PropertyChangedEventArgs(memberExpr.Member.Name));
  26.             }
  27.         }
  28.  
  29.         public string CustomerName
  30.         {
  31.             get
  32.             {
  33.                 return this.customerNameValue;
  34.             }
  35.  
  36.             set
  37.             {
  38.                 if (value != this.customerNameValue)
  39.                 {
  40.                     this.customerNameValue = value;
  41.                     NotifyPropertyChanged(() => CustomerName);
  42.                 }
  43.             }
  44.         }
  45.  
  46.         public string PhoneNumber
  47.         {
  48.             get
  49.             {
  50.                 return this.phoneNumberValue;
  51.             }
  52.  
  53.             set
  54.             {
  55.                 if (value != this.phoneNumberValue)
  56.                 {
  57.                     this.phoneNumberValue = value;
  58.                     NotifyPropertyChanged(() => PhoneNumber);
  59.                 }
  60.             }
  61.         }
  62.         }

As seen this is also cool way of avoiding the magic strings by using linq expressions. Finally a quick tip always create the base class (ViewModelBase) and encapsulate all the required functionalities in it. Then all your viewmodel classes must inherit this ViewModelBase class.

Hope you must have found this post useful. Please leave your valuable feedback in the comments section.

About these ads

1 Comment »

  1. Reblogged this on dotNuts.

    Comment by dotnuts — February 4, 2013 @ 4:43 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 69 other followers

%d bloggers like this: