概要
WPFでコントロールにオブジェクトをBindingしている場合、オブジェクトのプロパティが変更されたときにコントロールの表示も伴って更新されてほしいわけだが、残念ながら更新されない。
これは、更新されたことを通知する機構がオブジェクトに備わっていないからである。 このページではこれの対応策を示す。
対策
まず INotifyPropertyChanged インターフェースを実装
コントロールにプロパティが変更されたことを通知するには、まずバインドするクラスにINotifyPropertyChanged
インターフェースを実装しておく。
INotifyPropertyChanged
を実装するとPropertyChanged
イベントが追加されるので、これをコールするための下記のようなメソッドを作っておく。
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(name));
}
}
この引数name
には変更されたプロパティの名前を渡す。
そして変更を通知すべきプロパティ(表示を更新する必要のあるプロパティ)のset
アクセサで次のようにコールする。
private string _userId;
public string UserId
{
get
{
return _userId;
}
set
{
_userId = value;
OnPropertyChanged("UserId");
}
}
これでUserId
に値がセットされると、変更が通知されるようになる。
コレクションには ObservableCollection<T> クラス
たとえばTreeView
に階層構造のオブジェクトをバインドしているとする。
オブジェクトの中のコレクションをList<T>
などで実装しているとこれらのコレクションに要素が追加もしくは削除されたとき、TreeView
の表示が更新されない。 また、これはコレクションのプロパティからPropertyChanged
を呼んでも同じである。
これを自動的に反映されるようにするにはコレクションにObservableCollection<T>
クラスを利用すればいい。
ソースコード
以上の実装例を示す。
public class TopLevel : System.ComponentModel.INotifyPropertyChanged
{
private string _userId;
public string UserId
{
get
{
return _userId;
}
set
{
_userId = value;
OnPropertyChanged("UserId");
}
}
public ObservableCollection<SecondLevel> SecondLevels { get; set; }
#region INotifyPropertyChanged メンバー
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(name));
}
}
#endregion
}