その1:http://blogs.wankuma.com/kazuki/archive/2008/08/14/153008.aspx
.NET Framework 3.5 SP1で追加されたBindingGroupというクラス。
こいつは、結構使いでがあるんじゃないかと思ってる。正統派な使い方ではないのかもしれないけど、上手に使えばINotifyPropertyChangedインターフェースとか実装しなきゃいけないパターンが減るかもしれない。ということで実験。
まずは、Personクラスを作る。INotifyPropertyChangedは実装せずに、普通にプロパティを定義するだけ。定義するプロパティは、いつも通りNameとAgeの2つにした。
namespace WpfBindingGroupTest
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
これをWindowのDataContextへ設定する。最近はコードから設定するよりも、XAMLから設定するほうがお試しのときは楽なように感じてきだした。最初はコードからじゃないと嫌だったんだけど、慣れって恐ろしいわ。
<Window x:Class="WpfBindingGroupTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfBindingGroupTest"
Title="Window1" Height="300" Width="300"
DataContext="{DynamicResource tanaka}">
<Window.Resources>
<local:Person x:Key="tanaka" Name="田中 太郎" Age="50" />
</Window.Resources>
<Window.BindingGroup>
<BindingGroup />
</Window.BindingGroup>
<StackPanel>
<TextBlock Text="名前" />
<TextBox Text="{Binding Name}" />
<TextBlock Text="年齢" />
<TextBox Text="{Binding Age}" />
<Button Content="Update Source" Click="UpdateSource_Click" />
<Button Content="Source To Target" Click="SourceToTarget_Click" />
</StackPanel>
</Window>
ついでに、適当に画面を組み立てておいた。実行すると見た目はこんな感じ。
WindowのDataContextにPersonの田中 太郎さん50歳を設定する。そして、テキストボックスに名前と年齢をそれぞれバインドしておいた。BindingGroupをWindowに設定してWindow以下のBindingをさくっとグルーピング。Update Sourceは、CommitEditを呼んでPersonオブジェクトへテキストボックスの中身を書き戻す。
private void UpdateSource_Click(object sender, RoutedEventArgs e)
{
// 変更を反映
BindingGroup.CommitEdit();
}
ついに本題
さて、PersonクラスはINotifyPropertyChangedを実装していないので、Personオブジェクトの中身が書き換えられてもTextBoxの値って書き換わらない。もし、Personクラスの中身をTextBoxへ反映させようと思ったらName用のBindingとAge用のBindingすべてに対してメソッド呼び出しをして回らないといけなかったと思う。
BindingGroupを使うと、これがイッパツで出来るようになる。つまり、楽チンってこと。
private void SourceToTarget_Click(object sender, RoutedEventArgs e)
{
// リソースからPersonオブジェクトを取得して
var tanaka = (Person)FindResource("tanaka");
// データを初期化して
tanaka.Name = "田中 太郎";
tanaka.Age = 50;
// TextBoxのほうへ反映
BindingGroup.CancelEdit();
}
これで、どんなときもボタンを押すと「田中 太郎さん50歳」のデータが画面に出るようになる。INotifyPropertyChangedインターフェースだと、いっぱいプロパティを書き換えると、そのつど更新処理が走ってたけど、BindingGroupを使うことで、ここらへんを一まとめにしてドカーンと行えるようになる。
ありがたやありがたや。