Jeg arbejder for tiden en del med en Winform applikation, og har langt hen ad vejen implementeret MVVM, for at skille lidt af forretningslogikken ud fra UI koden. Mine model-klasser er derfor blevet fyldt med properties som rejser events hver gang de skifter værdi – modellen implementerer INotifyPropertyChanged. Jeg har derfor skrevet den samme kode igen og igen:
public object MyProperty{
get { return _myProperty; }
set {
if (value!=_myProperty)
{
_myProperty = value;
OnPropertyChanged("MyProperty");
}
}
}
Så var det lige jeg, som så mange gange før, blev inspireret af Mr. Rahien. Han foreslår at man laver en wrapper om de properties der skal rejse events, og lader dem implementerer interfacet. Min version kom til at se sådan ud:
public class Observable : INotifyPropertyChanged
{
private T _value;
public T Value
{
get { return _value; }
set
{
if (!value.Equals(_value))
{
_value = value;
OnPropertyChanged();
}
}
}
public static implicit operator T(Observable val)
{
return val.Value;
}
private void OnPropertyChanged()
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Value"));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Ud over at den wrapper letter arbejdet, og reducerer mængden af gentagelser, så gør den også View koden mere simpel. I stedet for at man skal have en PropertyChanged-handler med en switch, der undersøger hvilken property der rejste eventen, kan man nu hooke direkte op då de properties man finder interessante.
public class Model
{
public Observable<int> Current{ get; set; }
}
// Og mit view:
public class View
{
Model _model;
public View(Model model)
{
this._model = model;
model.Current.PropertyChanged += (s, e) => {/* Håndter skidtet */};
}
}
En anden lille detalje, er implicit operatoren – den sørger for at man kan behandle propertyen som om den bare var af typen T:
int next = model.Current + 1;
// I stedet for:
int next = model.Current.Value + 1;
Jeg elsker når man med et slag kan fjerne en masse kedelig kode.
Code on…