Wrap it yourself
Occasionally circumstances will prevent you from using ForView.Wrap() to wrap your view model. For example, prior to version 2009.3.1127, Telerik’s RadGridView for Silverlight did not support DependencyProperties: the DataContext of the rows had to implement INotifyPropertyChanged. Download the source code and follow along. The Silverlight DataGrid will be playing the part of the Telerik RadGridView control, even though DataGrid can bind to DependencyProperties just fine.
You can pick-and-choose which view models can be wrapped automatically and which can be wrapped manually. If your View Model implements INotifyPropertyChanged, then ForView.Wrap() will let it pass through. So we only need to implement INotifyPropertyChanged on the view model that represents a row in the grid.
public class PersonViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; }
There are 4 steps to implementing INotifyPropertyChanged on your own with Update Controls:
- Create a Dependent for each property.
- Initialize each Dependent with a lambda that calculates the value and assigns it to a field.
- In the getter of each property, call OnGet on the Dependent, then return the field.
- When the Invalidated event of each Dependent is fired, dispatch a call to the PropertyChanged event.
First we create a Dependent for each property. A Dependent is a sentry that guards the property and determines when it needs to be updated.
public class PersonViewModel : INotifyPropertyChanged { private Person _person; private Dependent _depFirst; public PersonViewModel(Person person) { _person = person; } public event PropertyChangedEventHandler PropertyChanged; }
Second, we initialize each Dependent with a lambda. When the Dependent needs to be updated, it will invoke this lambda. The lambda should calculate the dependent property and store it in a field.
public class PersonViewModel : INotifyPropertyChanged { private Person _person; private Dependent _depFirst; private string _first; public PersonViewModel(Person person) { _person = person; _depFirst = new Dependent(() => _first = _person.First); } public event PropertyChangedEventHandler PropertyChanged; }
Third, we call OnGet on the Dependent. OnGet will determine whether the Dependent is out-of-date. If so, it will invoke the lambda. The results of the calculation will be stored in a field. Return this field from the property getter.
public class PersonViewModel : INotifyPropertyChanged { private Person _person; private Dependent _depFirst; private string _first; public PersonViewModel(Person person) { _person = person; _depFirst = new Dependent(() => _first = _person.First); } public string First { get { _depFirst.OnGet(); return _first; } set { _person.First = value; } } public event PropertyChangedEventHandler PropertyChanged; }
Fourth, we use the Invalidated event of each Dependent to fire PropertyChanged. Invalidated is fired when the Dependent goes out-of-date. This occurs when any Independent property that the calculation reads is changed. The trick is that the PropertyChanged event needs to be dispatched, so that it will be fired after that change has completed. Otherwise the system will get stuck in an infinite update loop.
public class PersonViewModel : INotifyPropertyChanged { private Person _person; private Dependent _depFirst; private string _first; public PersonViewModel(Person person) { _person = person; _depFirst = new Dependent(() => _first = _person.First); _depFirst.Invalidated += () => FirePropertyChanged("First"); } public string First { get { _depFirst.OnGet(); return _first; } set { _person.First = value; } } public event PropertyChangedEventHandler PropertyChanged; private void FirePropertyChanged(string propertyName) { App.Current.RootVisual.Dispatcher.BeginInvoke(() => { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); }); } }
Hopefully you can let ForView.Wrap() handle data binding for you. But in those situations where you cannot, you could always wrap it yourself.

Recent comments
27 weeks 6 days ago