Mvvm-hooking-up-viewmodel
MVVM – ViewModelの接続
この章では、ViewModelを接続する方法について説明します。 ビューの最初の構成について説明した最後の章の続きです。 さて、最初の構築の次の形式は、 ViewModelLocator として知られる*メタパターン*です。 これは疑似パターンであり、MVVMパターンの上に階層化されています。
- MVVMでは、各ViewをViewModelに接続する必要があります。
- ViewModelLocatorは、コードを集中化し、ビューをさらに分離するためのシンプルなアプローチです。
- これは、ViewModelタイプとその構築方法を明示的に知る必要がないことを意味します。
- ViewModelLocatorを使用するにはさまざまなアプローチがありますが、ここでは、PRISMフレームワークの一部であるアプローチと最も類似したアプローチを使用します。
ViewModelLocatorは、ViewModelをViewに接続するプロセスを自動化する、ビューの最初の構築を行うための標準的で一貫性のある宣言的で疎結合の方法を提供します。 次の図は、ViewModelLocatorの高レベルプロセスを表しています。
- ステップ1 *-構築されているビュータイプを把握します。
- ステップ2 *-特定のビュータイプのViewModelを特定します。
- ステップ3 *-そのViewModelを構築します。
- ステップ4 *-Views DataContextをViewModelに設定します。
基本概念を理解するために、前の章の同じ例を続けて、ViewModelLocatorの簡単な例を見てみましょう。 StudentView.xamlファイルを見ると、ViewModelが静的に接続されていることがわかります。
次に、次のプログラムに示すように、これらの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"
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>
次のコードに示すように、新しいフォルダーVMLを作成し、単一の添付プロパティ(依存プロパティ)AutoHookedUpViewModelを含む新しいパブリッククラスViewModelLocatorを追加します。
public static bool GetAutoHookedUpViewModel(DependencyObject obj) {
return (bool)obj.GetValue(AutoHookedUpViewModelProperty);
}
public static void SetAutoHookedUpViewModel(DependencyObject obj, bool value) {
obj.SetValue(AutoHookedUpViewModelProperty, value);
}
//Using a DependencyProperty as the backing store for AutoHookedUpViewModel.
//This enables animation, styling, binding, etc...
public static readonly DependencyProperty AutoHookedUpViewModelProperty =
DependencyProperty.RegisterAttached("AutoHookedUpViewModel",
typeof(bool), typeof(ViewModelLocator), new PropertyMetadata(false,
AutoHookedUpViewModelChanged));
これで、基本的なアタッチプロパティの定義を確認できます。 プロパティに動作を追加するには、ViewModelをViewに接続する自動プロセスを含むこのプロパティの変更イベントハンドラーを追加する必要があります。 これを行うためのコードは次のとおりです-
private static void AutoHookedUpViewModelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e) {
if (DesignerProperties.GetIsInDesignMode(d)) return;
var viewType = d.GetType();
string str = viewType.FullName;
str = str.Replace(".Views.", ".ViewModel.");
var viewTypeName = str;
var viewModelTypeName = viewTypeName + "Model";
var viewModelType = Type.GetType(viewModelTypeName);
var viewModel = Activator.CreateInstance(viewModelType);
((FrameworkElement)d).DataContext = viewModel;
}
以下は、ViewModelLocatorクラスの完全な実装です。
using System;
using System.ComponentModel;
using System.Windows;
namespace MVVMDemo.VML {
public static class ViewModelLocator {
public static bool GetAutoHookedUpViewModel(DependencyObject obj) {
return (bool)obj.GetValue(AutoHookedUpViewModelProperty);
}
public static void SetAutoHookedUpViewModel(DependencyObject obj, bool value) {
obj.SetValue(AutoHookedUpViewModelProperty, value);
}
//Using a DependencyProperty as the backing store for AutoHookedUpViewModel.
//This enables animation, styling, binding, etc...
public static readonly DependencyProperty AutoHookedUpViewModelProperty =
DependencyProperty.RegisterAttached("AutoHookedUpViewModel",
typeof(bool), typeof(ViewModelLocator), new
PropertyMetadata(false, AutoHookedUpViewModelChanged));
private static void AutoHookedUpViewModelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e) {
if (DesignerProperties.GetIsInDesignMode(d)) return;
var viewType = d.GetType();
string str = viewType.FullName;
str = str.Replace(".Views.", ".ViewModel.");
var viewTypeName = str;
var viewModelTypeName = viewTypeName + "Model";
var viewModelType = Type.GetType(viewModelTypeName);
var viewModel = Activator.CreateInstance(viewModelType);
((FrameworkElement)d).DataContext = viewModel;
}
}
}
最初に行うことは、プロジェクトのルートにあるViewModelLocatorタイプにアクセスできるように、名前空間を追加することです。 次に、ビュータイプであるルート要素にAutoHookedUpViewModelプロパティを追加し、trueに設定します。
xmlns:vml = "clr-namespace:MVVMDemo.VML"
vml:ViewModelLocator.AutoHookedUpViewModel = "True"
これが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>
上記のコードをコンパイルして実行すると、ViewModelLocatorがその特定のビューのViewModelをフックしていることがわかります。
これについて注意すべき重要な点は、ビューがそのViewModelのタイプや構築方法に結合されていないことです。 これらはすべて、ViewModelLocator内の中央の場所に移動されました。