CommandBindingsにやられました。

WPF4には、ビルトインコマンドというものがある。その中の1つにApplicationCommands(System.Windows.Input)があり、以下のようなものを持つ。

・Cut(切り取り)
・Paste(貼り付け)
・Copy(コピー)
・Help(ヘルプファイル表示)
・Undo(1つ前の作業戻す)
・Redo(1つ後の作業実行)
・Close(閉じる)

これらのコマンドは、RoutedUICommandインターフェースを実装し、Routedイベントの様に子から親へ伝播する。
これらのコマンドと、自分が実行したいメソッドを結びつけるには、WindowクラスのCommandBindingsに登録する必要がある。
XAML上で書くとき

<Window x:Class="TawamureDays.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:nfc="http://nichia.jp/sys/foundation/component/gui"
xmlns:local="clr-namespace:TawamureDays"
Title="MainWindow" Height="213" Width="385">
<Window.CommandBindings>
<CommandBinding Command="New" Executed="ExecuteNewItemCommand"/>
</Window.CommandBindings>
<StackPanel/>
</Window>

Command="New"で、ApplicationCommands.Newを使っている事と同じになる。だからビルトイン。
Executedのメソッドは、コードビハインドで実装する必要がある。

/// <summary>
/// New(新規)コマンド実行用メソッド
/// </summary>
/// <param name="sender">発生元</param>
/// <param name="e">イベント引数</param>
private void ExecuteNewItemCommand(object sender, ExecutedRoutedEventArgs e) {
//新規作成で行う処理が実装されます。
return;
}

仕事上、添付プロパティを使って、このビルトインコマンドを使おうとすると、XAMLからの登録ではなく、コード上で登録/削除を実行する。
例えば、DataGridで貼り付けコマンド(Paste)を扱う時とかは、以下のようになる。
追加時

//貼付用コマンドをDataGridに登録します。
dataGrid.CommandBindings.Add(new CommandBinding(
ApplicationCommands.Paste,
CommandHelper.ExecutePastingData,
CommandHelper.CanExecutePastingData););

削除時

//貼付用コマンドをDataGridに削除します。
dataGrid.CommandBindings.Remove(new CommandBinding(
ApplicationCommands.Paste,
CommandHelper.ExecutePastingData,
CommandHelper.CanExecutePastingData););

しかし、実はこの実装には問題がある。通常のイベントハンドラにおいては、インスタンスを新たに作ってもきっちり削除してくれた。しかし、上記コードでは、CommandBindingsからは削除されてくれない事が最近わかった。Orz。
追加した時と同じインスタンスでないと、正常に削除されない。
なので、
追加時

var pasteBinding = new CommandBinding(
ApplicationCommands.Paste,
CommandHelper.ExecutePastingData,
CommandHelper.CanExecutePastingData);
//追加
dataGrid.CommandBindings.Add(pasteBinding);
//!このpasteBindingインスタンスをどこかに保管する。

削除時

//追加時に使ったインスタンス(pasteBinding)を取得する。
//削除
dataGrid.CommandBindings.Remove(pasteBinding);
とするしかない。CommandBindingsのClearメソッドを使ってしまうと、削除したくないものまで削除してしまいそうで怖い…。
正常に削除しないと、リークの元ネタとなって降り積もっていく…。
仕事上では一応解決はしたんだけどね…。ちゃんとデバッグで削除できていることを確認したらと思ったよ。
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m