3 - コードからの値の変更をUIに反映するバインディング
About
この項目ではコード側からバインディングしているデータを変更した場合に、その変更をUI上に反映させる方法についてあつかいます。この項目はこの前の項目2の内容を引き継ぐので参照順には注意してください。
INotifyPropertyChangedイベントの実装
項目の冒頭から酷く長いソースコードを掲載していますが、これがサンプルの2からサンプルの3にかけての変更点です。つまり、与えるデータの方に工夫を施すことによって、問題を解決しています。INotifyPropertyChangedインターフェースを実装し、プロパティの値が変更された場合に任意のタイミングでOnPropertyChangedイベントを通知し、UIに対して更新を促します。
ソースコードについては実は多く解説することはなく、典型的な値の変更と通知の形式となっています。注意する点も特にないと思われます。
public class SimpleClass : INotifyPropertyChanged { private string stringProperty; public string StringProperty { get{ return stringProperty; } set { if(value != stringProperty) { stringProperty = value; OnPropertyChanged("StringProperty"); } } } private bool boolProperty; public bool BoolProperty { get{ return boolProperty; } set { if(value != boolProperty) { boolProperty = value; OnPropertyChanged("BoolProperty"); } } } //INotifyPropertyChangedの実装 public event PropertyChangedEventHandler PropertyChanged; //INotifyPropertyChangedの実装 protected void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
悪い方向への副作用
少しのプロパティだけを持たせていたはずなのに、UIとデータとお互いに更新をフィードバックできるようにすると、クラスの実装がひどく大規模になってしまいました。回避策は多くの有識者によって検討されていますが、ここではその解説を割愛します。特に注意する点は、OnPropertyChangedの呼び出しの際にプロパティ名を文字列として扱っている点です。VisualStudioによる入力補助も効きませんし、リファクタによるプロパティ名の変更にも気を使わなければいけません。
実行と確認
実装されるUIはサンプル2とサンプル3とで変更されていません。2つ目のButtonをクリックして、データの書き換えを実行し、それがUI上にフィードバックされることを確認してください。
private void Button_Click1(object sender, RoutedEventArgs e) { Console.WriteLine(this.SimpleClassData.StringProperty); Console.WriteLine(this.SimpleClassData.BoolProperty); } private void Button_Click2(object sender, RoutedEventArgs e) { this.SimpleClassData.StringProperty = "From Codebehind."; this.SimpleClassData.BoolProperty = true; }
この項目の解説はこれで終わりです。