ChangeableObject and ValueConverter: databinding conveniences


A couple more bits of code that others might find useful…  Whenever I do databinding-intensive apps (both Silverlight & WPF), I find myself writing a fair amount of boilerplate code.  If you want change notifications on your class, you need to inherit from INotifyPropertyChanged, define a PropertyChanged event, and write a couple lines of code to fire it:


    if (this.PropertyChanged!= null) {
        var args = new PropertyChangedEventArgs(“SomeProperty”);
        PropertyChanged(this, args);
     }


Not rocket science, but it gets old after the 10th time.  How about a ChangeableObject base class?:


    public class ChangeableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;


        protected void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null) {
                var args = new PropertyChangedEventArgs(info);
                PropertyChanged(this, args);
            }
        }
    }


Now you can inherit the PropertyChanged event, and simplify firing it to a single line, e.g.:


    public class Elevator : ChangeableObject
    {
        private double position = 0;
        public double Position
        {
            get { return position; }
            set { position = value; NotifyPropertyChanged(“Position”); }
        }
    }


Similarly, it never ceases to annoy me that whenever I write a value converter, I’m forced to define a a ConvertBack method even though I almost never use it.  Plus, IntelliSense for implementing interfaces isn’t as strong as overriding virtual methods…  So here’s a trivial base class:


    public abstract class ValueConverter : IValueConverter
    {
        public abstract object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture);


        public virtual object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new Exception(“unsupported”);
        }
    }


Which can be used like this:


    public class BoolToVisibilityConverter : ValueConverter {
        public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var v = (bool)value;
            var result = (v) ? Visibility.Visible : Visibility.Collapsed;
            return result;
        }
    }


Comments (9)

  1. David says:

    Wouldn’t the first example be a good candidate for an extension method? Just imagine if your ValueConverter base class for some reason also had to implement INotifyPropertyChanged…

    static class NotifyPropertyChangedExtensions

    {

       public static void NotifyPropertyChanged(this INotifyPropertyChanged prop, String info)

       {

           if (prop.PropertyChanged != null) {

               var args = new PropertyChangedEventArgs(info);

               prop.PropertyChanged(prop, args);

           }

       }

    }

    Of course, you’d still have to implement the event…

  2. Steve says:

    @David:

    Can’t invoke the event at that place only from inside the class.

    And a safer way is:

    var propertyChanged = PropertyChanged;

    if (propertyChanged != null) {

       propertyChanged(this, new PropertyChangedEventArgs(info));

    }

  3. Joe says:

    Just to add my 2-cents worth….  Sometimes I find that in more complex notification objects that updating one property may have the effect of updating other property values as well.  Instead of calling this for each property that changed from within the CLR property’s "set" method, I use a version that can take take several property names:

    protected void NotifyPropertyChanges(params string[] names)

    {

      var propertyChanged = PropertyChanged;

      if (propertyChanged != null)

      {

         foreach (string name in names)

         {

            propertyChanged(this, new PropertyChangedEventArgs(name));

         }

      }

    }

  4. aelij says:

    You can find a more comprehensive implementation of ValueConverter, which also implements IMultiValueConverter and a MarkupExtension at http://codeplex.com/wpfcontrib/.

  5. Joe says:

    Right, to the multiple property point. Most of the time I raise this event with NULL – this indicates that all properties changed.

    If you have a large object of 20 or so properties and you are updating all of them it generates a lot of event traffic – especially for busy real-time apps.  A single "SynchronizeViews" type method works better and is more controlled.  It also lets you use the automatic property getters/setters.

  6. Eric Burke says:

    I went down the ChangeableObject path early on, but then I found that I needed a different base class in a number of cases, which made using it impossible.

    Because of that, I added a bunch of snippets that made it simple to type "inotify-Tab-Tab" and it would blast in the INotifyPropertyChanged implementation.  I also wrote snippets for a property that supported it so that I could type "propn-Tab-Tab" and get:

    private int _foo = 0;

    public int Foo

    {

      get { return _foo; }

      set

      {

         if(_foo != value)

         {

            _foo = value;

            RaisePropertyChanged("Foo");

         }

      }

    }

  7. Serge Baltic says:

    I think these helpers are only half-way through 😉

    For all of the value converters I usually employ a single non-abstract class that takes a conversion delegate in its ctor. A new type of converter could be created like this:

    ValueConverter.Create((byte n) => Color.FromArgb(0xFF, n, n, n));

    No class declarations needed to have one more converter defined. The object we create could be planted into the ResourceDictionary for further use from XAML markup thru a standard resource reference.

  8. Serge Baltic says:

    Now, the properties with notifications.

    The first alternative approach is to derive your object (directly or indirectly) from the DependencyObject class. This is possible for codebehind as well as for the UI classes. This enables us to declare our properties as Dependency Properties, which also guarantees that WPF will see any changes to them without our firing any special events. The pattern to declare a dependency property (a public static field and a CLR getter/setter) could easily be encoded as a R# Live Template / VS Code Snippet.

    The second alternative approach is to use a wrapper class to declare each of the properties, say, Property<TValue>. Inside it stores the actual value, exposes it through a CLR property (say, Value), and fires the appropriate events whenver the value is changed through a setter. This probably is the quickest way of writing the databindable code because it takes just one member, requires no special base classes, no interface implementations, no event declarations, no event firings, no nothing. The code to access the property gets longer, though (obj.Age.Value instead of obj.Age, for instance; {Binding Age.Value} in XAML), but in many cases I rule this to be a lesser inconvenience compared to setting up the rig for event notifications in each data object class.

  9. HankM says:

    Re: Halfway Through – 2 template approach

    Iteresting approach Serge.  Perhaps I’m missing something but isn’t it awkward to handle the property name and appropriate parent sender object (Nick’s original base class doesn’t give the parent either) when firing the event? EI the code:

    var args = new PropertyChangedEventArgs(PropertyName); // what name?

    propertyChanged(this, args); // what sender?

    Is there a more clever way than adding the overhead of the property name and owning object as members?