WPF で ViewModel から View の機能を呼び出すための ViewService.Wpf というライブラリを作成しました。
実際のView をサービスという形で ViewModel に公開し ViewModel はそのサービスを通して View の機能を呼び出せるため、ViewModel は View への依存を極力持たないように出来ます。
使い方
初めに ViewService.Wpf の簡単な使い方を説明します。
View に使用するサービスを定義
View のコードビハインドか、XAML のリソースに使いたいサービスを定義します。
次の例では、XAML でリソースに定義しています。
<Window xmlns:service="http://schemas.lumiria.com/view-services">
<ResourceDictionary>
<service:ViewServiceProvider x:Key="ViewServiceProvider">
<service:WindowService Key="Sub"
WindowType="{x:Type view:SubWindow}"
Owner="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" />
<service:MessageBoxService Owner="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" />
</service:ViewServiceProvider>
</ResourceDictionary>
</Window.Resources>
<!-- 省略 -->
</Window>
ViewModel でサービスを取得
View で定義した ViewServiceProvider を ViewModel に渡し、ViewModel はこの ViewServiceProvider から対象のサービスを取得します。
あとはサービスを通して View の機能を呼び出します。
var windowService = provider.Get<IWindowService>("Sub");
windowService.ShowDialog();
実際の使い方は、このサンプルを参考にしてください。
実装しているサービス
Ver 1.0.0 では次のサービスを実装しています。
WindowService
Window を表示するためのサービスです。
WindowActionService
対象の Window へのアクションを実行するサービスです。
ウィンドウを閉じたり、最大・最小化することが出来ます。
MessageBoxService
メッセージボックスを表示するためのサービスです。
まとめ
View が起点の処理ならば積極的にコードビハインドに実装すれば良いですが、どうしても ViewModel から View にアクセスしたいケースはあるかと思います。
そういうときはサービスやメッセンジャーといったパターンを使用すれば、ViewModel が View に直接依存するのを避けることが出来ます。
個人的には、メッセンジャーによる実装が一番良いと考えていますが、あまり手軽ではないように感じます。
ViewService.Wpf を使えば、利用頻度が高いと思われる View の機能をサービスとしてすぐに使うことが出来ます。