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