Edited at

[WPF備忘録 - その2] ICommand [Visual Studio 2008]

More than 1 year has passed since last update.


はじめに

皆さま方、お久しぶりです。前回の記事から随分と長い月日が経ってしまいました。

この間、新しい現場にアサインされたり、その新しい現場が渦中であったり、激動(?)の毎日を送ってまいりました。

今回は前回に引き続き、MVVMアーキテクチャパターンを導入するにあたりINotifyPropertyChangedインターフェースと同じくらい重要なインターフェース・ICommandについて記録していきます。

<< 他の記事へはこちらから >>


ICommand インターフェースとは?

ICommandインターフェースは、IChangedPropertyインターフェースに比べると少しだけ難解です。

とはいえ、イベントが1つにメソッドが2つなので、全然複雑ではありません。ご安心ください。

namespace System.Windows.Input

{
public interface ICommand
{
// CanExecute()の返す値が変わった場合, このイベント経由で変更があったことを通知する.
event EventHandler CanExecuteChanged;

// 現在の状態でこのコマンドを実行できるかどうかを判断するメソッドを定義する.
bool CanExecute(object parameter);
// コマンドの起動時に呼び出されるメソッドを定義する.
void Execute (object parameter);
}
}


ICommand インターフェースの実装

MVVMでいうところのViewから呼び出したいコマンド(≒処理)に対して、このICommand インターフェースを実装することで呼び出しが可能となります。以下、サンプルコード。

class HogeCommand : ICommand

{
/// <summary>
/// CanExecute()の返す値が変わった際に発火するイベントハンドラ.
/// </summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

/// <summary>
/// 現在の状態でコマンドを実行できるか判定するメソッド.
/// </summary>
/// <param name="parameter">XAML上で'CommandParameter'に指定した値. default=null.</param>
/// <returns>このコマンドを実行できる場合は true. それ以外は false .</returns>
public bool CanExecute(object parameter)
{
string text = parameter as string;
return !string.IsNullOrEmpty(text);
}

/// <summary>
/// 実行されるコマンドの実処理.
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
MessageBox.Show(parameter as string);
}
}

今回のサンプルコードは、View部分で指定した引数がnullでなければメッセージボックスでそれを表示するだけという簡素なものです。特に利用価値はありませんので、ご注意ください。

また、CanExecuteChangedイベントハンドラはMVVMで利用する場合, ほぼこの形での実装となると思うので定型文として覚えてしまっても問題ないと思います。


ICommandインターフェースの実際

上記のシンプルなICommandインタフェースの実装では、処理させたいコマンドが増えるたびに新規クラスを作成しなければならず、効率が悪いです。

そのため、普通はDelegateCommandやRelayCommandと呼ばれるクラスを作成し、それを使いまわすような実装にします。これらの話は次回のエントリで紹介いたしますのでご期待ください。


Viewと関連付けしたサンプル

前回紹介したINotifyPropertyChangedインターフェースの実装の続きとして書いていきます。


MainWindowViewModel.cs

using Wpf_MVVM_Sample.Model;

namespace Wpf_MVVM_Sample.ViewModel
{
class MainWindowViewModel : NotifyChangedBase
{
/// <summary>
/// [NEW]
/// Viewからコマンドに対してアクセスさせるためのプロパティ.
/// </summary>
public ICommand HogeCmd { get; private set; }

/// <summary>
/// Label表示用プロパティ.
/// </summary>
public string Text
{
get { return _text; }
private set
{
if (value != null && value != _text)
{
_text = value;
this.OnPropertyChanged("Text");
}
}
}
private string _text;

/// <summary>
/// コンストラクタ.
/// </summary>
public MainWindowViewModel()
{
this.Text = "Sample";
this.HogeCmd = new HogeCommand(); // インスタンス化を忘れずに!!
}
}
}


XAMLに対してButtonを追加します。


MainWindow.xaml

<Window x:Class="Wpf_MVVM_Sample.View.MainWindow"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Wpf_MVVM_Sample.ViewModel"
Title="MainWindow" Height="300" Width="300">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<!-- Nameプロパティを設定する -->
<Label
Name="label" Width="120"
Height="28" Margin="12,12,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="{Binding Text}" />

<!-- NEW: ButtonとViewModelの紐づけも行う -->
<Button
Width="75" Margin="17.502,56.447,0,0"
HorizontalAlignment="Left" VerticalAlignment="Top"
Command="{Binding HogeCmd}"
CommandParameter="{Binding ElementName=label, Path=Content}"
Content="Execute" />
</Grid>
</Window>


上記のようにすれば、Buttonを押下した際にメッセージボックスが表示されるようになります。

次回はICommandインターフェースの実装パターンの一つであるDelegateCommandについて書いていきます。


あとがき

今後は週一で頑張って書いていきたいなと思います(努力目標)。