MVVM –WPFデータバインディング
この章では、データバインディングがMVVMパターンをサポートする方法を学習します。データバインディングは、MVVMをMVCやMVPなどの他のUI分離パターンと区別する重要な機能です。
データバインディングの場合、ビューまたはUI要素のセットを構築する必要があります。次に、バインディングが指す他のオブジェクトが必要です。
ビューのUI要素は、ViewModelによって公開されるプロパティにバインドされます。
最初にビューについて説明したように、ViewとViewModelが構築される順序は状況によって異なります。
ViewとViewModelが構築され、ViewのDataContextがViewModelに設定されます。
バインディングは、ViewとViewModelの間でデータをやり取りするためのOneWayまたはTwoWayデータバインディングのいずれかです。
同じ例のデータバインディングを見てみましょう。以下はStudentViewのXAMLコードです。
<UserControl x:Class = "MVVMDemo.Views.StudentView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:local = "clr-namespace:MVVMDemo.Views"
xmlns:viewModel = "clr-namespace:MVVMDemo.ViewModel"
xmlns:vml = "clr-namespace:MVVMDemo.VML"
vml:ViewModelLocator.AutoHookedUpViewModel = "True"
mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
<!--<UserControl.DataContext>
<viewModel:StudentViewModel/>
</UserControl.DataContext>-->
<Grid>
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path = Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode = OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
上記のXAMLコードを見ると、ItemsControlがViewModelによって公開されているStudentsコレクションにバインドされていることがわかります。
Studentモデルのプロパティにも独自の個別のバインディングがあり、これらはTextboxesとTextBlockにバインドされていることもわかります。
ビューの全体的なDataContextがViewModelに設定されているため、ItemsControlのItemSourceはStudentsプロパティにバインドできます。
ここでのプロパティの個々のバインディングもDataContextバインディングですが、ItemSourceの動作方法のため、ViewModel自体に対してバインディングしていません。
アイテムソースがそのコレクションにバインドされると、レンダリング時に各アイテムのコンテナがレンダリングされ、そのコンテナのDataContextがアイテムに設定されます。したがって、行内の各テキストボックスとテキストブロックの全体的なDataContextは、コレクション内の個々のStudentになります。また、TextBoxのこれらのバインディングはTwoWayデータバインディングであり、TextBlockの場合はTextBlockを編集できないため、OneWayデータバインディングであることがわかります。
このアプリケーションを再度実行すると、次の出力が表示されます。
ここで、最初の行の2番目のテキストボックスのテキストをAllainからUpstonに変更し、Tabキーを押してフォーカスを失います。TextBlockテキストも更新されていることがわかります。
これは、TextBoxのバインディングがTwoWayに設定されており、モデルも更新され、モデルから再度TextBlockが更新されるためです。