半人前プログラマーの技術談議

開発した物と,C#を入門者向けに解説した記事を書いています!

【C# GUI】MVVM② デリゲートコマンド part4-8【WPF XAML】

calendar

こんにちは!シロウです!

今回は,前回のMVVM開発の続きです.

MVVM開発

アウトプット部分のデータバインディング

数字列を表示する為のテキストボックスとバインドする為に,

MainWindowVMクラスにCreatedNumberプロパティを追加します.

テキストボックスから,TextプロパティにCreatedNumberプロパティをバインドします.

データバインディングを確認する為に,

MainWindowVMクラスのコンストラクタで,CreatedNumberプロパティを設定してみます.

実行して確認してみます.

CreatedNumberプロパティに設定した値がテキストボックスに表示されている事が確認できます.

 

デリゲートコマンド

データバインディングは,UI要素のプロパティとViewModelクラスのプロパティをバインドする機能です.

バインドできるのはプロパティであり,メソッドはバインドできません.

その為,メソッドをプロパティとして扱うことができるデリゲートを使います.

 

WPFでは,ボタンのクリック時に処理を行うときにはCommandプロパティを使います.

Commandプロパティに設定する値は,ICommandインターフェースを実装したクラスです.

このプロパティをボタンのCommandプロパティとバインドすると,ボタンクリック時に処理を実行する事ができます.

ViewModelで,ICommandインターフェースを実装したクラスを作成し,そのクラスを外部に公開します.

ソリューションエクスプローラーで,WPF_RandomNumberプロジェクトを右クリックして,追加→クラスの順に選択します.

クラス名は「DelegateCommand」という名前にします.

外部に公開するので,アクセス修飾子「public」を付けます.

また,ICommandインターフェースを実装します.

ICommandインターフェースはSystem.Windows.Input名前空間に属するので,

usingディレクティブを追加します.

ICommandインターフェースにマウスカーソルを合わせて,

電球ボタンから「インターフェースを実装します。」をクリックします.

ICommandインターフェースを実装する時に必要なメソッドなどのコードが自動的に生成されます.

Executeメソッドは,コマンドの実行時に呼び出されるメソッドです.

CanExecuteメソッドは,実行条件を指定するメソッドです.(ボタンの有効,無効とか)

今回はこの2つのメソッドのthrow文を削除して,コンストラクタで受け取ったデリゲートに処理を委ねます.

Executeはvoid型のメソッドなのでAction型,

CanExecuteはbool型の戻り値のメソッドなのでFunc<bool>型の変数を用意します.

外部からの干渉を受けないようにprivateで宣言します.

コンストラクタで,引数を代入します.

Executeメソッドからexecuteデリゲートを,

CanExecuteメソッドからcanexecuteデリゲートを呼び出します.

最後に,CanExecuteChangedイベントです.

コマンドを実行するかどうかに影響するような変更があった場合に発生します.

イベントはaddアクセサーとremoveアクセサーを持っています.

addアクセサーはイベントハンドラーを登録,

removeアクセサーはイベントハンドラーを削除する処理を記述します.

CommandManagerクラスは,コマンドを管理するクラスです.

このクラスのRequerySuggestedイベントは,イベントハンドラーを登録,削除することによって,

コマンドの実行条件を満たしているかどうかを常時監視しています.

 

DelegateCommandクラスの記述は大体同じ書き方をするので,

最初はテンプレートだと思ってコピペしてもいいかもしれません.(使い方の方が重要なので)

 

DelegateCommand型プロパティ

ボタンクリック時に呼び出されるCommandプロパティにバインドするDelegateCommand型のプロパティをMainWindowVMクラスに作成します.

プロパティ名は「MakeNumber」にします.

setアクセサーにprivate修飾子を付けて,ViewModel(MainWindowVMクラス)以外から干渉を受けないようにします.

 

数字列を生成するメソッドを作成

このメソッドは,DelegateCommandクラスのインスタンスの生成時に必要な1番目の引数に設定するメソッドです.

NumberGeneratorクラスを呼び出す為に,RandomNumberのusingディレクティブを追加します.

メソッド名は「MakeNumberExecute」にします.

NumberGeneratorクラスのMakenumberを呼び出し,

戻り値をCreateNumberプロパティに設定します.

 

処理を行う条件を決めるメソッドを追加

このメソッドは,DelegateCommandクラスのインスタンス生成時に必要な2番目の引数に設定するメソッドです.

引数の型はFunc<bool>デリゲートなので,引数が無い,bool型の戻り値を持つメソッドです.

メソッド名は「CanMakeNumberExecute」にします.

今回は,1~20文字の数字列に限定するように指定します.

 

MakeNumberプロパティに値を設定

MakeNumberプロパティに値を設定します.

この処理はコンストラクタで行います.

MakeNumberプロパティは,DelegateCommand型なので,インスタンスを生成して格納します.

引数には,先ほど作成したMakeNumberExecuteメソッドとCanMakeNumberExecuteメソッドを設定します.

 

コマンドのデータバインディング

View(MainWindow.xaml)に切り替え,ボタンのCommandプロパティにMakeNumberプロパティをバインドします.

実行して確認します.

文字数を0に設定してみます.

ボタンがグレーアウトされ,無効になります.

これは,処理の実行条件を満たしていないからです.(CanMakeNumberExecuteメソッドの戻り値がfalseになった)

文字数を10に戻して,ボタンをクリックしてみます.

ボタンを押しても,数字列が表示されません.

これは,プロパティの値が変更されたときにUI要素の値を更新する機能がWPFに無い為です.

なので,自分でこの機能を追加する必要があります.

次回は,この変更通知機能を実装します.

 

今回記述した,MainWindowVMクラスのコードを記載しておきます.