プロパティが変更された事を View に通知するためには INotifyPropertyChanged インタフェースを実装したクラスを作りますよね。
普通の方法
INotifyPropertyChanged インタフェースは PropertyChanged イベントハンドラを実装しないといけないのでこんな感じ。
public class MainPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
PropertyChanged を呼び出す手間を減らすための NotifyPropertyChanged を一緒に定義しています。
プロパティが変化したときには このイベントを呼ん変更を通知します。
public class MainPageViewModel : INotifyPropertyChanged { private string _name; public string Name { get { return this._name; } set { this._name = value; // 変更の通知 NotifyPropertyChanged("Name"); } }
これでプロパティの変更が View に通知されるのですが、なんというか...スッキリしませんよね。特にプロパティ名を文字列で渡しているあたり。
サンプルアプリで見かける方法
サンプルを見ていると BindableBase という名前のクラスがあって、もう少しだけスマートに INotifyPropertyChanged インタフェースを処理してくれています。
public abstract class BindableBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { var eventHandler = this.PropertyChanged; if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); } } }
使い方はこんな感じ。
public class MainPageViewModel : BindableBase { private string _name; public string Name { get { return this._name; } set { SetProperty(ref this._name, value); } }
ref を指定しないといけないのがちょっとアレですが、だいぶマシになっていますよね。サンプルで見かけて以来、自分のアプリにもコピーして使っていました。
Prism の場合
Prism だと その名も ViewModel というクラスがあって、こんな感じになります。
public class MainPageViewModel : ViewModel { private string _name; public string Name { get { return this._name; } set { SetProperty(ref this._name, value); } }
あれ? 使い方まったく同じですね。
この ViewModel の定義はこんな感じ
public class ViewModel : BindableBase, INavigationAware { // 略 } public abstract class BindableBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged(string propertyName) { var eventHandler = this.PropertyChanged; if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); } } protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression) { var propertyName = PropertySupport.ExtractPropertyName(propertyExpression); this.OnPropertyChanged(propertyName); } }
あ、一緒だこれー。
という訳で、サンプルをベースにしてアプリ作っていた人には Prism がとっつきやすいのではないでしょうか?