Tuesday, August 19, 2008

Generic SetValue Method for INotifyPropertyChanged

I needed a generic SetValue method for my objects that implemented INotifyPropertyChanged, since all my setters looked like:

image

... and I wanted something like:

image

... and here's the end result: (applied to a base object which all other INotifyPropertyChanged objects inherit from)

image

It shortened my 650 line code file to 325 lines :)

for copy and paste:

protected void SetValue<T>(ref T valueToSet, T newValue, string propertyName)

        {

            if (valueToSet == null || !valueToSet.Equals(newValue))

            {

                if (!(valueToSet == null && newValue == null))

                {

                    valueToSet = newValue;

                    RaisePropertyChanged(propertyName);

                }

            }

        }

Notes:

  • The ref parameter was necessary (as apposed to returning T), because TwoWay binding to the object will not work in Silverlight (and I assume WPF) if the actual property is changed after the PropertyChanged event is fired.
  • All that null checking is necessary to take into account ref / value types. The null check in the first if statement ensures that the valueToSet.Equals does not throw a NullReferenceException, and the null checks in the second if statement ensures that if the original value is null, that the new value is something other than null (ie: has changed)

Extending SetValue Method with VerifyProperty Method

I came across this great post for implementing a base BindableObject, which does a little more than I'd like, but one cool idea is to add a VerifyProperty method, so while developing, you can catch any spelling mistakes in the propertyName parameter.
It uses reflection to ensure that the property indeed does exist on the object, and makes use if conditional compilation so the code is not deployed to the release build - like so:

image

follow the link for a demo project. (rename the extension to .zip)

... so the modified SetValue method would look like:

protected void SetValue<T>(ref T valueToSet, T newValue, string propertyName)

        {

            if (valueToSet == null || !valueToSet.Equals(newValue))

            {

                if (!(valueToSet == null && newValue == null))

                {

                    VerifyProperty(propertyName);

                    valueToSet = newValue;

                    RaisePropertyChanged(propertyName);

                }

            }

        }

    
   

No comments: