WPFでデータ操作を行う場合には、一般的にWindowやUserControlのDataContextに操作対象データを設定します。
そうするとたとえばTextBoxのコンテンツにバインディング
<TextBox Text={Binding Path=Target}/>
するだけで値を勝手にバインドしてくれます。
この場合.DataContext.Targetの中身がバインドされます。
-
このバインドしたデータを更新したときに画面などに反映させるには通常INotifyPropertyChangedインターフェイスを実装します。
このインターフェイスは event PropertyChangedEventHandler PropertyChangedを提供します。
何か変更があったときはこのイベントをたたくと言う約束をするわけです。
PropertyChangedEventHandler の詳細はMSDNみてもらうとして、簡単にいうと変更されたプロパティ名を文字列側でイベント先に通知するってことをします。
今回のobj.Targetに変更があった場合にはobj側(ContextClassとします)に、NotifyPropertyChanged("Target"); と書くのが典型的な実装になります。
これを実現するためにはContextClassは単なるデータの固まりではいけません。すべてをプロパティで実装し、且つそのsetにthis._Target = value;と上記のNotifyPropertyChangedを実装しなくてはいけません。
-
しかも、それだけではありません。
このobj.Targetがstringなどの単純な型ではなく、classである場合にはデータ的にobj.Target.Nameが変更されるかもしれません。
その場合にはTergetもINotifyPropertyChangedを実装する必要があります。
想定しているバインド式
<TextBox Text={Binding Path=Target.Name}/>
これでどのような値でもWPF側に通知できるようになりました。
-
ただしこれにコンバータを絡ませてくると話が別です。
コンバータとはSystem.Windows.Data.IValueConverterの実装クラスのことです。
コンバータを利用するには
<TextBox Text={Binding Path=Target, Converter={StaticResource conv}}/>
このようなバインド式を書くTargetをパラメータにconvがよばれて、その結果がバインドされます。
独自の書式や編集を加える場合にはこれを使います。
これの場合にはバインドしている実体はTargetになります。
INotifyPropertyChangedはobjがTargetの変更されたという通知をしなくてはいけません。
プログラムで下記のようなコードを書いたとします。
obj.Target.TargetName="変更通知はでるかな?";
結果はもちろんNGです。変更通知が受け取れないためです。
対処するにはTargetのクラスがINotifyPropertyを持っているはずなので、伝播させる必要があります。
public ContextClass()
{
this._target.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
if(this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Target"));
}
};
}
これでばっちり反映されるようになります。
問題はTargetに当たる物が、INotifyPropertyChangedを実装していない場合。
これはラッパなりヘルパなりで出入りを監視するかプロクシを作成するかを判断しなくてはいけません。
おわり
2日なやみました(^^;;;;