MVVM –WPFデータテンプレート

テンプレートは、コントロールの全体的な外観と外観を記述します。コントロールごとに、そのコントロールに外観を与えるデフォルトのテンプレートが関連付けられています。WPFアプリケーションでは、コントロールの視覚的な動作と視覚的な外観をカスタマイズするときに、独自のテンプレートを簡単に作成できます。ロジックとテンプレート間の接続は、データバインディングによって実現できます。

MVVMには、ViewModelの最初の構築として知られている別の主要な形式があります。

  • ViewModelの最初の構築アプローチは、WPFの暗黙的なデータテンプレートの機能を活用します。

  • 暗黙的なデータテンプレートは、データバインディングを使用する要素について、現在のリソースディクショナリから適切なテンプレートを自動的に選択できます。これは、データバインディングによってレンダリングされるデータオブジェクトのタイプに基づいて行われます。まず、データオブジェクトにバインドしている要素が必要です。

最初にデータテンプレート、特に暗黙的なデータテンプレートを利用してビューモデルを実行する方法を理解する簡単な例をもう一度見てみましょう。これがStudentViewModelクラスの実装です。

using MVVMDemo.Model; 
using System.Collections.ObjectModel;

namespace MVVMDemo.ViewModel { 

   public class StudentViewModel {
	
      public StudentViewModel() { 
         LoadStudents(); 
      } 
		
      public ObservableCollection<Student> Students { 
         get; 
         set; 
      }
		
      public void LoadStudents() { 
         ObservableCollection<Student> students = new ObservableCollection<Student>();
			
         students.Add(new Student { FirstName = "Mark", LastName = "Allain" }); 
         students.Add(new Student { FirstName = "Allen", LastName = "Brown" }); 
         students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" }); 
			
         Students = students; 
      } 
   } 
}

上記のViewModelが変更されていないことがわかります。前の章と同じ例を続けます。このViewModelクラスは、Studentsコレクションプロパティを公開し、構築時にそれを設定するだけです。StudentView.xamlファイルに移動し、既存の実装を削除して、[リソース]セクションでデータテンプレートを定義しましょう。

<UserControl.Resources> 
   <DataTemplate x:Key = "studentsTemplate">
	
      <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> 
</UserControl.Resources>

次のコードに示すように、リストボックスを追加し、そのリストボックスをStudentsプロパティにデータバインドします。

<ListBox ItemsSource = "{Binding Students}" ItemTemplate = "{StaticResource studentsTemplate}"/>

リソースセクションでは、DataTemplateにstudentsTemplateのキーがあり、実際にそのテンプレートを使用するには、ListBoxのItemTemplateプロパティを使用する必要があります。これで、リストボックスに特定のテンプレートを使用してそれらの生徒をレンダリングするように指示していることがわかります。以下は、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.Resources> 
      <DataTemplate x:Key = "studentsTemplate"> 
		
         <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> 
   </UserControl.Resources>
	
   <Grid> 
      <ListBox 
         ItemsSource = "{Binding Students}" 
         ItemTemplate = "{StaticResource studentsTemplate}"/> 
   </Grid>
	
</UserControl>

上記のコードをコンパイルして実行すると、次のウィンドウが表示されます。このウィンドウには1つのリストボックスが含まれています。各ListBoxItemには、TextBlockボックスとTextボックスに表示されるStudentクラスのオブジェクトデータが含まれています。

これを暗黙的なテンプレートにするには、次のコードに示すように、リストボックスからItemTemplateプロパティを削除し、テンプレート定義にDataTypeプロパティを追加する必要があります。

<UserControl.Resources> 
   <DataTemplate DataType = "{x:Type data:Student}">
	
      <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> 
</UserControl.Resources>
 
<Grid> 
   <ListBox ItemsSource = "{Binding Students}"/> 
</Grid>

DataTemplateでは、x:Typeマークアップ拡張機能は非常に重要であり、XAMLの演算子のタイプと同様です。したがって、基本的には、MVVMDemo.Model名前空間にあるStudentデータ型を指す必要があります。以下は、更新された完全な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:data = "clr-namespace:MVVMDemo.Model" 
   xmlns:vml = "clr-namespace:MVVMDemo.VML" 
   vml:ViewModelLocator.AutoHookedUpViewModel = "True" 
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300">
	
   <UserControl.Resources> 
      <DataTemplate DataType = "{x:Type data:Student}"> 
		
         <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> 
   </UserControl.Resources>
	
   <Grid>
      <ListBox ItemsSource = "{Binding Students}"/> 
   </Grid> 
	
</UserControl>

このアプリケーションを再度実行すると、適切なDataTemplateを見つけることによってレンダリングされるオブジェクトのタイプが自動的にマッピングされるため、データテンプレートを使用したStudentsの同じレンダリングが引き続き得られます。

理解を深めるために、上記の例を段階的に実行することをお勧めします。