最近WPFやSilverlight関連の記事なんかを見てると、ちょくちょく添付動作(AttachedBehavior)というものにお目にかかることがあります。
この添付動作というものは、WPF誕生当初やSilverlight2誕生当初から組み込みである機能ではなくて、添付プロパティとかを上手に使うことで、まるで後からコントロールに動作を追加で出来るといったものです。
具体的に、どのようなシーンで使われているかというと、WPFにあるCommand機能はボタンにしかないけど、TextBoxでEnterが押されたときにCommandのExecuteを実行する動作を付け足したりとか、TreeViewItemがアクティブになったときに、自動的にそのTreeViewItemの位置までスクロールする動作を付け足したりとかっていったことに使われたりします。
今回は、超簡単な添付動作として、TextBoxでEnterキーを押すと、メッセージボックスに現在入力しているテキストが表示されるというものを作ってみようと思います。
プロジェクトの作成
WpfAttachedBehaviorという名前でWPFアプリケーションを作成します。
最初に作成されるWindow1.xamlにTextBoxを追加して実行してちゃんと動くか確認します。
実行して適当にふじこを入力してみたところ。
このTextBoxに、動作を添付するものを作っていきます。
早速作る
添付動作と名前がついていても、実際には添付プロパティを使います。
TextBoxBehaviorという名前のクラスを作成します。
そこにEnterCommandという名前の添付プロパティを定義します。
public static class TextBoxBehavior
{
/// <summary>
/// TextBoxでEnterキーを押したときに、入力内容をMessageBoxで表示する動作を追加する。
/// </summary>
public static bool GetEnterCommand(DependencyObject obj)
{
return (bool)obj.GetValue(EnterCommandProperty);
}
public static void SetEnterCommand(DependencyObject obj, bool value)
{
obj.SetValue(EnterCommandProperty, value);
}
public static readonly DependencyProperty EnterCommandProperty =
DependencyProperty.RegisterAttached("EnterCommand",
typeof(bool),
typeof(TextBoxBehavior),
new UIPropertyMetadata(false));
}
これだと、まだTextBoxに何も動作を追加してないので、さくっと動作を追加する処理を書いていきます。
動作を追加するタイミングは、EnterCommandプロパティの値が変わった時がいいのでコールバックを指定します。
public static readonly DependencyProperty EnterCommandProperty =
DependencyProperty.RegisterAttached("EnterCommand",
typeof(bool),
typeof(TextBoxBehavior),
new UIPropertyMetadata(false, EnterCommandChanged)); // コールバックを指定
/// <summary>
/// EnterCommandプロパティが変更されたときに呼び出される。
/// trueが設定された時に、KeyDownイベントハンドラを追加して、falseの時にKeyDownイベントハンドラを
/// 削除する。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public static void EnterCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
}
EnterCommandChangedのコメントに書いてある通り、ここにKeyDownイベントハンドラの登録・削除処理を書きます。
public static void EnterCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
if (GetEnterCommand(textBox))
{
textBox.KeyDown += new System.Windows.Input.KeyEventHandler(textBox_KeyDown);
}
else
{
textBox.KeyDown -= new System.Windows.Input.KeyEventHandler(textBox_KeyDown);
}
}
textBox_KeyDownイベントハンドラでは、Enterキーが押されたときにMessageBoxを表示する処理を書きます。
private static void textBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.None && e.Key == Key.Enter)
{
var textBox = sender as TextBox;
MessageBox.Show(textBox.Text);
}
}
以上で添付動作は完成です。
使ってみよう
ということで、最初に作った画面のTextBoxに今作った添付動作を追加してみようと思います。
名前空間の定義をWindow1.xamlのWindowタグあたりに追加します。
xmlns:l="clr-namespace:WpfAttachedBehavior"
そして、TextBoxにTextBoxBehavior.EnterCommandプロパティを設定します。
<TextBox l:TextBoxBehavior.EnterCommand="True" />
以上で完成!動かしてみます。
実行して適当にふじこを入力
Enterキーを押すと、メッセージボックスが出る
添付動作って便利。