ViewModelLocatorとは何か、どのように機能するのか、DataTemplateと比較してそれを使用することの賛否両論について簡単な概要を教えてもらえますか?
私はGoogleで情報を見つけようとしましたが、それの多くの異なる実装があり、それが何であるか、そしてそれを使用することの賛否両論について明確なリストがないようです。
MVVMでの通常のプラクティスは、ビューが 依存性注入 (DI)コンテナーから解決することにより、ViewModelを見つけるようにすることです。これは、コンテナがViewクラスのインスタンスを提供(解決)するように求められたときに自動的に発生します。コンテナーinjects ViewModelパラメーターを受け入れるViewのコンストラクターを呼び出して、ViewModelをViewに入れます。このスキームは制御の反転(IoC)と呼ばれます。
ここでの主な利点は、実行時にコンテナを構成できることであり、要求する型を解決する方法についての指示があります。これにより、アプリケーションを実際に実行するときに使用する型(ViewsおよびViewModels)を解決するように指示することにより、テスト性が向上しますが、アプリケーションの単体テストを実行する場合は異なる指示をします。後者の場合、アプリケーションはUIさえも持たないので(実行されず、テストのみが実行されます)、コンテナはアプリケーションの実行時に使用される「通常の」タイプの代わりに mocks を解決します。
これまで、DIアプローチでは、アプリケーションコンポーネントの作成の上に抽象化レイヤーを追加することで、アプリケーションのテスト容易性を実現できることがわかりました。このアプローチには1つの問題があります:Microsoft Expression Blendなどのビジュアルデザイナーとうまく機能しません。
問題は、通常のアプリケーションの実行と単体テストの実行の両方で、誰かがset up解決するタイプの指示を含むコンテナを必要とすることです。さらに、ViewModelsがビューに挿入できるように、ビューを解決するために誰かがaskコンテナを作成する必要があります。
ただし、設計時には実行中のコードはありません。デザイナーはリフレクションを使用してビューのインスタンスを作成しようとします。つまり、次のことを意味します。
DataContext
はnull
になるため、デザイナーで「空の」ビューを取得します。これはあまり有用ではありませんViewModelLocatorは、次のように使用される追加の抽象化です。
もちろん、これは、ビューが最初にパラメーターなしのコンストラクターを持たなければならないことを意味します(そうでない場合、デザイナーはインスタンス化できません)。
ViewModelLocatorは、MVVMアプリケーションでDIの利点を維持しながら、ビジュアルデザイナーとコードをうまく連携させるイディオムです。これは、アプリケーションの「ブレンド可能性」と呼ばれることもあります(Expression Blendを参照)。
上記を消化した後、実際の例を参照してください here 。
最後に、データテンプレートを使用することは、ViewModelLocatorを使用する代わりではなく、UIの一部に明示的なView/ViewModelペアを使用する代わりになります。多くの場合、代わりにデータテンプレートを使用できるため、ViewModelのViewを定義する必要はないことがわかります。
@ Jon's answer の実装例
ビューモデルロケータークラスがあります。各プロパティは、ビューに割り当てるビューモデルのインスタンスになります。コードがデザインモードで実行されているか、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}}">
この質問の他の回答がデザイナーを包み込む理由がわかりません。
View Model Locatorの目的は、Viewでこれをインスタンス化できるようにすることです(はい、View Model Locator = View First)。
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コンテナーのラッパーです。
参照する: