UI にデータをバインドしたとき、OK ボタンを押すまで入力内容をソースに反映させたくない場合があります。例えば設定ダイアログとか。
BindingGroup を利用すれば、入力内容をデータソースに一括で反映させることができます。入力内容の検証も可能です。
BindingGroup を使った UI のサンプルコードは次の通り。
<Window x:Class="BindingGroupSample.AccountView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Window.BindingGroup> <!--バインドしたデータを一括で検証/反映するための BindingGroup--> <BindingGroup Name="AccountBindings" NotifyOnValidationError="True"/> </Window.BindingGroup> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Content="ID" Grid.Column="0" Grid.Row="0"/> <Label Content="Password" Grid.Column="0" Grid.Row="1"/> <TextBox Grid.Column="1" Grid.Row="0"> <TextBox.Text> <!-- BindingGroupName を指定したものは一括で検証と更新ができる --> <!-- UpdateSourceTrigger には Explicit を指定しておくこと--> <Binding Path="Id" Mode="TwoWay" BindingGroupName="AccountBindings" UpdateSourceTrigger="Explicit"/> </TextBox.Text> </TextBox> <TextBox Grid.Column="1" Grid.Row="1"> <TextBox.Text> <Binding Path="Password" Mode="TwoWay" BindingGroupName="AccountBindings" UpdateSourceTrigger="Explicit"/> </TextBox.Text> </TextBox> <StackPanel Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" FlowDirection="RightToLeft" Orientation="Horizontal"> <Button Content="OK" Click="Button_Click"/> </StackPanel> </Grid> </Window>
データを更新する場合は、BindingGroup の UpdateSources メソッドを呼び出せば OK。
public partial class AccountView : Window { public AccountView() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { // UpdateSources メソッドを呼び出して、 // 入力内容を反映させる。 if (BindingGroup.UpdateSources()) { // TODO: 成功したときの処理 } } }
ところで、Model-View-ViewModel パターンの場合、どうすればいいんだろう?
- Button の Click イベントハンドラ内で UpdateSources メソッドを呼び出してから ViewModel の Command を呼び出す
- ViewModel に View への参照を渡して、ViewModel 側で UpdateSources メソッドを呼び出す
思いついたのはこの2つ。どちらもピンと来ないな。