回答:
MVVMでは、通常、依存関係注入(DI)コンテナーからビューを解決することにより、ビューがビューモデルを見つけるようにします。これは、コンテナーがViewクラスのインスタンスを提供(解決)するように要求されたときに自動的に発生します。コンテナは、ViewModelパラメータを受け入れるViewのコンストラクタを呼び出すことにより、ViewModelをViewに注入します。このスキームは、制御の反転(IoC)と呼ばれます。
ここでの主な利点は、リクエストしたタイプを解決する方法の指示により、実行時にコンテナーを構成できることです。これにより、アプリケーションの実際の実行時に使用するタイプ(ビューとビューモデル)を解決するように指示し、アプリケーションの単体テストを実行するときに異なる方法で指示することで、テスト容易性を高めることができます。後者の場合、アプリケーションにはUIさえありません(実行されていません。テストのみです)。そのため、コンテナーは、アプリケーションの実行時に使用される「通常の」タイプの代わりにモックを解決します。
これまでのところ、DIアプローチでは、アプリケーションコンポーネントの作成に抽象化レイヤーを追加することで、アプリケーションのテスト容易性が実現されることを確認しました。このアプローチには1つの問題があります。MicrosoftExpression Blendなどのビジュアルデザイナーではうまく機能しません。
問題は、通常のアプリケーションの実行と単体テストの実行の両方で、解決するタイプの指示を誰かがコンテナに設定する必要があることです。さらに、誰かがしなければならない頼むのviewmodelsがそれらに注入することができるように、ビューを解決するための容器を。
ただし、デザインタイムには実行中のコードはありません。デザイナーは、リフレクションを使用してビューのインスタンスを作成しようとします。つまり、
DataContext
になりますnull
私たちは「デザイナーの『空』ビューちゃうので-非常に便利ではありませんViewModelLocatorは、次のように使用される追加の抽象化です。
もちろんこれは、ビューには最初にパラメーターのないコンストラクターが必要であることを意味します(そうしないと、デザイナーはインスタンス化できません)。
ViewModelLocatorは、MVVMアプリケーションでDIの利点を維持しながら、コードをビジュアルデザイナーとうまく連携させることができるイディオムです。これは、アプリケーションの「ブレンド可能性」と呼ばれることもあります(Expression Blendを指します)。
上記を消化した後、実際の例を参照してくださいここに。
最後に、データテンプレートの使用は、ViewModelLocatorの使用に代わるものではなく、UIの一部に明示的なView / ViewModelペアを使用することに代わるものです。代わりにデータテンプレートを使用できるため、ViewModelのビューを定義する必要がないことがよくあります。
d:DataContext="{d:DesignInstance MockViewModels:MockMainWindowModel, IsDesignTimeCreatable=True}"
。ロケーターの目的は、WPFがDIを提供するのが非常に悪いため、ビューでDIを実際に有効にすることです。例:ダイアログウィンドウを開くメインウィンドウがあります。通常の方法でダイアログウィンドウのDIを解決するには、メインウィンドウへの依存関係としてそれを渡す必要があります!これは、ビューロケータで回避されます。
@Jonの回答の実装例
ビューモデルロケータークラスがあります。各プロパティは、ビューに割り当てるビューモデルのインスタンスになります。コードがデザインモードで実行されているかどうかを確認できますDesignerProperties.GetIsInDesignMode
。これにより、設計時にモックモデルを使用し、アプリケーションを実行しているときに実際のオブジェクトを使用できます。
public class ViewModelLocator
{
private DependencyObject dummy = new DependencyObject();
public IMainViewModel MainViewModel
{
get
{
if (IsInDesignMode())
{
return new MockMainViewModel();
}
return MyIoC.Container.GetExportedValue<IMainViewModel>();
}
}
// returns true if editing .xaml file in VS for example
private bool IsInDesignMode()
{
return DesignerProperties.GetIsInDesignMode(dummy);
}
}
そして、それを使用するために、ロケーターをApp.xaml
リソースに追加できます。
xmlns:core="clr-namespace:MyViewModelLocatorNamespace"
<Application.Resources>
<core:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
次に、ビュー(例:MainView.xaml)をビューモデルに接続します。
<Window ...
DataContext="{Binding Path=MainViewModel, Source={StaticResource ViewModelLocator}}">
this
代わりにを使用することに違いはありますdummy
か?
この質問の他の回答がなぜデザイナーを取り巻くのか理解できません。
ビューモデルロケーターの目的は、ビューでこれをインスタンス化できるようにすることです(はい、ビューモデルロケーター=最初に表示)。
public void MyWindowViewModel(IService someService)
{
}
これだけではなく:
public void MyWindowViewModel()
{
}
これを宣言することによって:
DataContext="{Binding MainWindowModel, Source={StaticResource ViewModelLocator}}"
ViewModelLocator
IoCを参照するクラスはどこにあり、それはMainWindowModel
それが公開するプロパティを解決する方法です。
モックビューモデルをビューに提供することとは関係ありません。それが必要な場合は、
d:DataContext="{d:DesignInstance MockViewModels:MockMainWindowModel, IsDesignTimeCreatable=True}"
View Model Locatorは、Unityなどの一部の(任意の)Inversion of Controlコンテナーのラッパーです。
参照する: