LoginSignup
13
13

More than 5 years have passed since last update.

WPF/MVVM/C#/Prism5.0 ViewModelLocationProvider ~ViewとViewModelを自動で関連付け~

Posted at

WPFでMVVMは難しい

残念なことに、WPFでMVVMパターンを適用する際には、.NET標準だけ使うとなると、綺麗でわかりやすく保守が容易なコードが書けません。
書けないような基盤しかないのです。
なので、PrismなどのMVVM基盤ライブラリが必要となります。
https://msdn.microsoft.com/ja-jp/library/gg406140.aspx

他にも様々なライブラリが公開されていますが、MS謹製ということで今回はPrismを利用しようと思います。
Prismを利用することで得られるメリットを公開します。
以下の予定です。

  1. BindableBase/DelegateCommand ~ViewModelの基盤~
  2. ErrorsContaier ~便利なエラー通知~
  3. ViewModelLocationProvider ~ViewとViewModelを自動で関連付け~
  4. Regionってなんなのさ ~Viewの配置をお手軽に~
  5. IModuleとUnity ~UIでDI~
  6. DIPパターンの恩恵 ~MSBuildで並列ビルド~

本稿は上記3の記事になります。

※Visual Studio 2013 Community Editionで実験しています。

ViewModelLocationProvider

これまでやってきたサンプルでは、ViewとViewModelの紐付けは以下のようになっています。

CalcView.xaml.cs
using Microsoft.Practices.Prism.Mvvm;
using System.Windows;

namespace KStore.Calc._2
{   
    public partial class CalcView : Window
    {
        public CalcView()
        {
            InitializeComponent();
            this.DataContext = new CalcViewModel(); // <-- ここで紐づけ
        }
    }
}

この
this .DataContext = new CalcViewModel();

を自動でやってくれるというちょっとオーバースペックな機能がPrismにはあります。
いや、オーバースペックではなく、今後必要になるのですが、まだあまり必要性は感じられません。
とにかく、やってみます。

CalcView.xamlに以下の2行を追加します。

CalcView.xaml
<Window x :Class="KStore.Calc._2.CalcView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local ="clr-namespace:KStore.Calc._2"
        mc:Ignorable ="d"
        Title="Calc" Height ="350" Width="525"
        xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
        prism:ViewModelLocator.AutoWireViewModel ="True"
        >
</Window>

このままビルドすると、ビルドは通りますが、以下のように怒られます。

Your views must implement IView

実行してみると以下の例外。
Image.png

言われたとおりに、CalcViewにIViewを実装。これはほとんどマーカーインタフェースですね。
DataContextにViewModelを紐付けする行も削除しました。

CalcView.xaml.cs
using Microsoft.Practices.Prism.Mvvm;
using System.Windows;

namespace KStore.Calc._3
{   
    public partial class CalcView : Window, IView // <-- このインターフェースを追加
    {
        public CalcView()
        {
            InitializeComponent();
        }
    }
}

で、実行してみると・・・
Image.png

バインドされていない。。。
何故か。

ViewModelLocationProviderのコードを見ると、
Viewの名前に加えて、"ViewModel"が必要みたいです。
今は、
CalcView -> CalcViewModelにしていたのですが、
CalcView -> CalcViewViewModel でないとダメみたいです。

うーん。Viewの名前は末尾に"View"にしないほうが良さそうですね。

気を取り直して、CalcViewViewModel にしてみて、実行します。

Image.png

バインドされました!
これを使うには、ViewModelの命名規則を必ず
Viewの名前 + "ViewModel"とする必要があります。

上記はXAMLのみで完結する記載でしたが、XAMLで記載せず、コードビハインドで以下のように書いてもOKです。

CalcView.xaml.cs
using Microsoft.Practices.Prism.Mvvm;
using System.Windows;

namespace KStore.Calc._3
{   
    public partial class CalcView : Window, IView
    {
        public CalcView()
        {
            InitializeComponent();
            ViewModelLocationProvider.AutoWireViewModelChanged(this);
        }
    }
}

今回はあまり長くならずに済みました。

まとめ

ViewModelLocationProviderを使うには、Viewの名前とViewModelの名前に規則性を持たせる必要があります。
Viewの名前に "ViewModel"を末尾に加えます。
例:
CalcView -> CalcViewViewModel

Viewの名前は末尾に"View"をつけないほうが良さそう。

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13