コマンド
最終更新:
atachi
コマンドを利用することで、コマンドが設定されたコンポーネントの意味とコマンドが実際に行うロジックとの関係が切り離される。
右クリックメニューの「切り取り」「コピー」「貼り付け」はコマンドの代表例である。それぞれの意味は誰しも知っているが、各コマンドがどのような処理を行うかは各アプリケーションが実装しなければならない。
WPFのコマンドもこのような意味であると捉えることができる。
コマンドとは実行されるアクションで、ICommandを継承しアクションを実装します。
コマンドの呼び出しは、コマンドソースから行います。
コマンドソースとはコマンドを呼び出す対象の要素です。ICommandSource を実装したクラスです。
WFPではButtonクラスやMenuItemクラスが実装済みです。
コマンドターゲットとはコマンドを実行する対象の要素です。
コマンドの呼び出し
ボタンが押された時にコマンドを呼び出したい場合は、Button.Commandに呼び出したいコマンドを指定します。
<Button Command="ApplicationCommands.Open">
<Image Source="images/FileOpen.png"></Image>
</Button>
<Button Command="ApplicationCommands.Open" CommandParameter="パラメータ">
<Image Source="images/FileOpen.png"></Image>
</Button>
CommandParameter属性はコマンドのハンドラに渡されるパラメータです。
ICommand.Execute の引数にそのまま渡されます。
コード上からコマンドを呼び出したい場合は、Execute()をコールします。
ApplicationCommands.Paste.Execute(null,textbox1);
コマンドの対象
発行されたコマンドを受け取り、コマンドを実行する要素を対象と呼びます。
次の例ではメニューバーから「貼り付け(ApplicationCommands.Paste)」というコマンドを発行した場合に、そのコマンドの実行対象としてmainTextBoxを指定しています。
<StackPanel>
<Menu>
<MenuItem Command="ApplicationCommands.Paste"
CommandTarget="{Binding ElementName=mainTextBox}" />
</Menu>
<TextBox Name="mainTextBox"/>
</StackPanel>
コマンドの『中身』の実装
Windowsアプリケーションでよく使用される「保存」というコマンドは、その意味は誰でも知っているが、何をどのように保存するかはアプリケーションによって異なる。
テキストエディタならばファイルに文字列を保存する事を指しますし、ペインタなどのグラフィックソフトならばビットマップを任意の画像形式で保存します。
このようにコマンドがどのような処理を行うかは、アプリケーション側で実装する必要があります。
あるコマンドを受け取ったときの処理を結びつけることをコマンドバインディングと呼びます。
コマンドバインディングは分離コード、またはXAMLに記述することができます。
コマンドバインディングをコードで実装する場合は、CommandBindingを使用します。
public partical class MainWindow : Window {
public MainWindow() {
InitializeComponent();
// コマンドバインディングの定義
CommandBinding cb = new CommandBinding();
cb.Command = ApplicationCommands.Open; // バインドしたいコマンドの種類
cb.Executed += new ExecutedRoutedEventHandler(onOpenExecuter);
this.CommandBinding.Add( cb );
}
private void onOpenExecuter(object sender, ExecutedRoutedEventArgs e) {
}
}
また、このコードの等価実装をXAMLで記述することもできます。
<Window>
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Execute="onOpenExecuter" />
</Window.CommandBindings>
</Window>
カスタムコマンドの作成
オリジナルのコマンドを実装したい場合、RoutedCommand または RoutedUICommand の静的なインスタンスを定義します。
static RoutedUICommand StartUp = new RoutedUICommand(
"アプリケーションのスタートアップ", "StartUpCommand", typeof(MainWindow));
ICommandを使用したコマンドクラスの実装
namespace my {
// コマンドが実行された場合に、任意の処理(アクション)を呼び出す
public class RelayCommand : ICommand {
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public RelayCommand(Action execute, Func<bool> canExecute) {
_execute = execute;
_canExecute = canExecute;
}
// ICommand Members
public bool CanExecute(object parameter) {
// コマンドが実行可能か??
// _canExecuteが設定されている場合は、_canExecuteを使用するが、
// 設定されていない場合は常に「true」とする。
//
return _canExecute == null ? true : _canExecute();
}
// ICommand Members
public event EventHandler CanExecuteChanged {
add {
CommandManager.RequerySuggested += value;
}
remove {
CommandManager.RequerySuggested -= value;
}
}
// ICommand Members
public void Execute(object parameter) {
// コマンド実行時の処理
_execute();
}
}
}
コマンドソースの作成
コマンドソースとはコマンドを発行できるオブジェクト要素です。
C#コードを使えばコマンドは自由に発行できるのですが、XAMLからコマンドを発行したい場合はオブジェクト要素がコマンドソースとなるように実装しなければなりません。
コマンドソースとなるには ICommandSource を継承したオブジェクト要素を作成します。
ButtonクラスはICommandSourceを継承しているので、ICommandSource.CommandによってButtonがクリックされたときに発行するコマンドを指定します。
コマンドソースを実装する場合、ICommandが発行するCanExecuteChangedイベントをハンドリングします。
CanExecuteChangedはICommandが実行可能である場合にtrueを取得できるイベントで、コマンドが発行可能であるかユーザーに知らせることができます。