はじめに
私が仕事で作成しているアプリケーションの UI では、Enter キーを押すと次のコントロールにフォーカスを移動するコードをよく書きます。昔からそういう仕様みたいなので。
ただ、何度も同じコードを記述するのは面倒です。かといって、その機能のためだけに、新しいコントロールを作るのもイマイチ。
そこで添付ビヘイビアに目を付けました。
添付ビヘイビアについて
添付ビヘイビアとは、添付プロパティを上手く使って、コントロールに機能を後から付ける手法です。
さっそく添付ビヘイビアを作成してみます
using System.Windows; using System.Windows.Input; namespace AttachedBehaviorSample { public static class UIElementBehavior { // 添付プロパティの初期値は false。 // コールバックを指定しておく。 public static readonly DependencyProperty EnterCommand = DependencyProperty.RegisterAttached("EnterCommand", typeof(bool), typeof(UIElementBehavior), new UIPropertyMetadata(false, EnterCommandChanged)); public static bool GetEnterCommand(DependencyObject obj) { return (bool)obj.GetValue(EnterCommand); } public static void SetEnterCommand(DependencyObject obj, bool value) { obj.SetValue(EnterCommand, value); } // EnterCommand の値が変更されたときに呼び出される。 // KeyDown イベントハンドラの登録&解除を行う。 public static void EnterCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { UIElement element = sender as UIElement; if (element == null) { return; } if (GetEnterCommand(element)) { element.KeyDown += textBox_KeyDown; } else { element.KeyDown -= textBox_KeyDown; } } // Enter キーが押されたら、次のコントロールにフォーカスを移動する private static void textBox_KeyDown(object sender, KeyEventArgs e) { if ((Keyboard.Modifiers == ModifierKeys.None) && (e.Key == Key.Enter)) { UIElement element = sender as UIElement; element.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } } } }
添付ビヘイビアを使ってみます
<Window x:Class="AttachedBehaviorSample.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:AttachedBehaviorSample" Title="Window1" Height="300" Width="300"> <Window.Resources> <!-- フォーカスがある TextBox の背景色を変更するスタイル --> <Style TargetType="{x:Type TextBox}"> <Style.Triggers> <Trigger Property="IsFocused" Value="True"> <Setter Property="Background" Value="SkyBlue"/> </Trigger> </Style.Triggers> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBox Grid.Row="0" local:UIElementBehavior.EnterCommand="True"/> <TextBox Grid.Row="1" local:UIElementBehavior.EnterCommand="True"/> <TextBox Grid.Row="2" local:UIElementBehavior.EnterCommand="True"/> </Grid> </Window>
Window の上に配置した TextBox 全てに設定。フォーカスがあるコントロールが一目で分かるよう、トリガーで背景色を変更するようにしています。
まとめ
何度も記述するのは面倒、かといってカスタムコントロールを作るまでもない。そんな「ちょっとした機能」を使いまわせるよう実装するのに、添付ビヘイビアは適してると思います。
添付ビヘイビアって便利!