Condividi tramite


Bubbling PropertyChanged Events in Silverlight

I’ve been working with Silverlight (specifically for Windows Phone 7) recently and something I’ve found useful is the ability to “bubble” PropertyChanged event up. So for example;

    1:      public class MainPageViewModel : INotifyPropertyChanged
    2:      {
    3:          public ObservableCollection<Person> People
    4:          {
    5:              get
    6:              {
    7:                  return  _repository.Items;
    8:              }
    9:          }
   10:   
   11:          // ... other members ommitted
   12:      }

In this situation I have a repository of Person objects, and that repository implements INotifyPropertyChanged. But I don’t want to expose the repository as part of my View Model because that defeats the point of my encapsulation!

Now, if the ObservableCollection contents change, my View will get notified via the CollectionChanged event and will update itself. But if the repository destroys and replaces the whole collection, the View will never be notified.

As a solution to this, I created a very simple class, as follows;

 

    1:      public class NotifyPropertyChangedBubbler
   2:      {
   3:          private INotifyPropertyChanged _source;
   4:          private PropertyMap[] _propertyNames;
   5:          private Action<string> _target;
   6:
   7:          public NotifyPropertyChangedBubbler(
   8:              INotifyPropertyChanged source,
   9:              PropertyMap[] propertyNames,
  10:              Action<string> target)
  11:          {
  12:              _source = source;
  13:              _propertyNames = propertyNames;
  14:              _target = target;
  15:
  16:              _source.PropertyChanged +=
  17:                  new PropertyChangedEventHandler(PropertyChanged);  
  18:          }
  19:
  20:          private void PropertyChanged(object sender, PropertyChangedEventArgs e)
  21:          {
  22:              var map = _propertyNames.FirstOrDefault(
  23:                  pm => pm.Source == e.PropertyName);
  24:              if (map != null)
  25:              {
  26:                  _target(map.Target);
  27:              }
  28:          }
  29:      }

And in my View Model I use it like this;

    1:      public MainPageViewModel()
    2:      {
    3:          var maps = new[] 
    4:          {
    5:              new PropertyMap("Items", "People")
    6:          };
    7:          _bubbler = new NotifyPropertyChangedBubbler(
    8:              _repository, maps, OnPropertyChanged);
    9:      }

 You’ll notice I can map one property name to another – because on my Repository the collection is named Items, but it is exposed through my View Model as People. The last argument to the bubbler’s constructor is the current class’ OnPropertyChanged function, which in turn raises the event.

This seems to work quite well. Does anyone have another approach? I feel like there should be a less-code solution, so I’m open to suggestions.

 

Original Post by Simon Ince on 19th October 2010 here: https://blogs.msdn.com/b/simonince/archive/2010/10/19/bubbling-propertychanged-events-in-silverlight.aspx