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が更新されるためです。