Mix11に使われていたと思われるコードが落ちていのたでつらつらと眺めていたら、ちょっと変わった方法でViewModelを定義していましたのでご紹介します。
普通のViewModelの場合
普通にViewModelを定義する場合こんな感じになるのではないでしょうか。PropertyChangedに対応したプロパティが増えるとViewModelの見通しが悪くなります。
public class BasicViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(string propertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } public class BasicViewModel : BasicViewModelBase { private string text = string.Empty; /// <summary> /// プロパティの定義に行数を使いすぎて見通しが悪くなる。 /// </summary> public string Text { get { return this.text; } set { if (!Equals(this.text, value)) { this.text = value; this.RaisePropertyChanged("Text"); } } } }
Mix11のサンプルにあったViewModelの場合
それに対して、refをうまく使ってSetValueメソッドを書くことによって、ViewModelに実際に書くプロパティの行数を減らしています。GetValueはSetValueと同じようにgetterを書くために用意したものと思います。
public class MixViewModelBase : INotifyPropertyChanged { protected void SendPropertyChanged(string propertyName) { var e = new PropertyChangedEventArgs(propertyName); PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler(this, e); } } public event PropertyChangedEventHandler PropertyChanged; protected T GetValue<T>(T field) { return field; } protected void SetValue<T>(string propertyName, ref T field, T newValue) { if (!object.ReferenceEquals(field, newValue) && (newValue == null || !newValue.Equals(field))) { field = newValue; this.SendPropertyChanged(propertyName); } } } public class MixViewModel : MixViewModelBase { private string text = string.Empty; /// <summary> /// バインディングソース用プロパティの書き方がちょっとだけ簡潔になるけど /// ref使っているのがちょっと・・・ /// </summary> public string Text { get { return this.GetValue(this.text); } set { this.SetValue("Text", ref this.text, value); } } }
個人的にはrefを使うのがちょっとキモイ気もしますが、簡潔に書く一つの方法としてはありかもしれません。