【C# WPF】WPFを理解したいC#初心者の話【MVVMパターン編その2】

C# WPFについて学んでいく過程を備忘録として残して置きたいと思います。

1. MVVMパターンの設計


前回は、電卓系のアプリケーションを開発するにあたって、あらかじめ必要そうな機能をいくつか挙げて、それをMVVMパターンにあてはめてみました。

今回は、実際にMVVMパターンでのアプリケーションの開発を体験してみたいと思います。

2. プロジェクトを整える


早速Visual Studioを起動して、電卓系のアプリケーションを開発していきます。

プロジェクトを作るところまでの手順は、Hello Worldアプリケーションのときと同じです。

プロジェクト名に関して、今回は「CalcApp」としています。


プロジェクトを作成したら、今度はプログラムを作る前にMVVMパターンに応じてフォルダーを作成してみます。

今回作成するフォルダは以下の4つです。

・Views
・ViewModels
・Models
・Common


「Views」「ViewModels」「Models」に関しては、前回までで説明したMVVMパターンに応じた要素をそれぞれのフォルダーに格納するために作ります。

「Common」に関しては、MVVMパターンでは分類しない機能やその他必要な機能を格納するためのフォルダーです。


フォルダーを作成するには、Visual Studioの画面左側の「ソリューションエクスプローラー」の上で右クリックをし、「追加」→「新しいフォルダー」を選択してください。

新しいフォルダーが追加されたら、名前を設定してください。


フォルダーを作成したら、既にある「MainWindow.xaml」と「MainWindow.xaml.cs」を移動します。

これらはViewの要素に当てはまる画面側の部分ですので、「Views」フォルダに移動します。

移動の際、名前空間の調整に関するメッセージが出てきますので、今回は自動で調整をしてもらいましょう。


ファイルの移動を行ったら、今度はファイルパスについて設定を行う必要があります。

変える必要があるファイルは「MainWindow.xaml」と「App.xaml」です。

MainWindow.xaml側は、XAMLビューを開いて最初の行にある「x:Class="CalcApp.MainWindow"」の部分を変更します。

変更後は「x:Class="CalcApp.Views.MainWindow"」としてください。

これは、作成時はCalcAppフォルダー直下においてあったMainWindow.xamlが、CalcAppフォルダー内のViewsフォルダーの中に移動した為、設定側も同じように設定する必要があるためです。


App.xaml側は、XAMLビューを開いて下のほうにある「StartupUri="MainWindow.xaml">」の部分を変更します。

ここは「StartupUri="Views\MainWindow.xaml">」とします。


ここまで終われば、今度は「MainWindow.xaml.cs」に変更を加えます。

MainWindow.xaml.csのコードエディターを開くと、「namespace CalcApp」という記述を探してください。

見つけたらこの部分を「namespace CalcApp.Views」に変更してください。


ここまでの手順を完了したら、一度ビルドしてみましょう。

ビルドが失敗してしまう場合は、もう一度ここまでの手順をひとつずつ確認し直してみてください。

ビルドが完了したら次の手順に進みましょう。

3. ViewModelとModelも作る


ViewModelsとModelsのフォルダーの中身にファイルを作成します。

まずはソリューションエクスプローラーのModelsフォルダーを右クリックして「追加」→「新しい項目」を選択します。

作成テンプレートから「クラス」を選択し、今回は名前を「MainModel.cs」とし、追加を押して新しいcsファイルを追加します。

ViewModelsも同様の手順でクラス用のcsファイル「MainViewModel.cs」を追加します。

4. ViewModelに基本的な機能を追加する


MVVMパターンでは、ViewModelの機能として「表示している値に変更があったとき、View側にそれを通知する」という機能を作る必要があります。

その通知を行う為に、先ほど作成したMainViewModelクラスに機能を追加していきます。


まずはインターフェースである「NotifyPropertyChanged」を実装します。

MainViewModel.csのMainViewModelクラス内に以下のコードを記述してみます。

class MainViewModel:INotifyPropertyChanged
    {
        // 変数の変更通知用
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

ここまでで一度ビルドを行い、問題がないかを確認しておきましょう。

5. コマンド機能を作る


今度はMVVMでのボタン操作に必要なCommandについてを作ります。

MVVMではボタン操作を行う際にCommandでバインドをする必要があります。


そのために、Commandのインターフェースを実装したクラスを使用します。

こちらは「Common」フォルダーにクラスを追加します。

先ほどクラスを追加した手順と同様に「RelayCommand.cs」を追加します。

以下のコードを記述してください。

public class RelayCommand:ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;


        public event EventHandler CanExecuteChanged;
        public RelayCommand(Action execute)
            : this(execute, null)
        {
        }

        public RelayCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        public void Execute(object parameter)
        {
       &nb

6. まとめ

今回は電卓系のアプリケーションをMVVMパターンで開発するにあたっての下地作りを行っていきました。

次回以降では、MVVMパターンを意識しながら、アプリケーションの本体部分である計算の処理やGUIの配置を作ってみます。