MVVM を意識した内部構造

 Visual Studio 2013 において、デフォルトの WPF アプリケーションプロジェクトの内部構造から、 MVVM パターンを意識した内部構造にするための方法を紹介します。

 WPF によるデスクトップアプリケーションを開発する場合、Visual Studio では "WPF アプリケーション" というプロジェクトを選択して開発を進めます。 新規プロジェクトを作成するとき、Fig.1 のように Visual C# の下にある "WPF アプリケーション" を選択し、ソリューション名を決定して下さい。

Fig.1 : 新しいプロジェクト作成ダイアログ
WPF アプリケーションのデフォルトの内部構造はFig.2 のように App クラスと MainWindow クラスのみとなっています。 また、参照設定を見ると、コンソールアプリケーションに比べて PresentationCore、PresentationFramework、System.Xaml、WindowsBase の外部参照が追加されています。
Fig.2 : デフォルトの内部構造
一方、WPF はUI とロジックを明確に切り分けて開発を進めることができる MVVM パターンによるプログラミングを支援するシステムとして知られています。 これを有効活用するにはデフォルトの内部構造では少し不便ですので、使いやすいように変更して使います。

 具体的には次のような作業となります。

  • MainWindow.xaml(および MainWindow.xaml.cs)を削除
  • "Views"、"ViewModels"、"Models" という名前のフォルダをツリーに追加
  • "Views" フォルダに "MainView.xaml" をウィンドウとして追加
  • "ViewModels" フォルダに "MainViewModel.cs" をクラスとして追加
  • App.xaml 内で定義されている StartupUri 属性を削除
  • App.xaml.cs 内で OnStartup() メソッドをオーバーライド、編集

 以上の作業をおこなった後の内部構造は Fig.3 のようになります。

Fig.3 : MVVM パターンを意識した内部構造
また、編集した App.xaml および App.xaml.cs は Code 1、Code 2 のようになります。
<Application x:Class="Section2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>
Code 1 : StartupUri プロパティを削除した App.xaml
namespace Section2
{
    using System.Windows;
    using Section2.Views;
    using Section2.ViewModels;

    /// <summary>
    /// App.xaml の相互作用ロジック
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            var w = new MainView();
            var vm = new MainViewModel();

            w.DataContext = vm;
            w.Show();
        }
    }
}
Code 2 : OnStartup メソッドを override した App.xaml.cs
このように MainView の DataContext に対して MainViewModel を指定することで、 MainView と MainViewModel の間でデータバインディング機能を用いたデータのやり取りができるようになります。 しかし、データバインディング機能を使用するためには、 ViewModel 側は INotifyPropertyChanged インターフェースや ICommand インターフェースを実装したプロパティを公開する必要があります。

Designed by CSS.Design Sample