WPFのTextBoxのEnterキーの挙動の変更♯2

前回の投稿でTextBoxでEnterキーを入力したときの挙動を変更する添付プロパティの設計の一部をしました。この投稿は、残りの設計とnugetライブラリーとして公開したことについてです。

TextBoxのEnterキーの挙動を制御する添付プロパティ

TextBoxのEnterキーの挙動を制御できる添付プロパティを作成します。

添付プロパティは、TextBoxコントロールに設定して利用するものとします。他のコントロールに設定した場合は、設定は無視されるものとします。

添付プロパティの名前は、TextBox.AcceptsReturnプロパティの名前に合わせて、Enterキー(Return)が入力されたときの挙動という意味で、ReturnBehaviorとします。

<TextBox 
    nsAttachedProps:TextBoxProperties.ReturnBehavior="UpdateSource"/>
...

PreviewKeyDownイベントのイベントハンドラー

コントロールのキーダウンのイベントは、PreviewKeyDownイベント、KeyDownイベントの順番で処理されます。

TextBoxの既存のKeyDownイベントハンドラーで処理される前に、処理したいので、PreviewKeyDownイベントハンドラーを利用します。

PreviewKeyDownのイベントハンドラーでは、Enterキーが押されたときのみ、添付プロパティReturnBehaviorに指定された挙動を実行します。ただし、TextBox.AcceptsReturnプロパティがtrueのときは、Enterキーは改行入力に使われるので、このイベントハンドラーでは処理しません。

PreviewKeyDown のイベントハンドラーの実装として、具体的には以下のようなコードを用意します。

static void OnPreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
    if (e.Key != System.Windows.Input.Key.Enter
        || !(sender is TextBox tb)
        || tb.AcceptsReturn)
    {
        return;
    }

    var mode = GetReturnBehavior(tb);

    if (mode == ReturnBehaviorMode.None) { return; }

    var modifiers = Keyboard.Modifiers;

    if(modifiers == ModifierKeys.None)
    {
        if (mode.HasFlag(ReturnBehaviorMode.UpdateSource))
        {
            var bindingExpression = BindingOperations.GetBindingExpression(tb, TextBox.TextProperty);
            bindingExpression?.UpdateSource();
            e.Handled = true;
        }

        if (mode.HasFlag(ReturnBehaviorMode.SelectAll))
        {
            tb.SelectAll();
            e.Handled = true;
        }
    }

    if (modifiers == ModifierKeys.None || modifiers == ModifierKeys.Shift)
    {
        if (mode.HasFlag(ReturnBehaviorMode.MoveFocus))
        {
            var direction = modifiers == ModifierKeys.Shift ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
            var focused = FocusManager.GetFocusedElement(tb) as FrameworkElement;
            if (focused == null && tb.IsFocused)
            {
                focused = tb;
            }
            focused?.MoveFocus(new TraversalRequest(direction));

            e.Handled = true;
        }
    }
}

添付プロパティReturnBehaviorに指定された挙動は、基本の挙動に分割して処理します。

Noneの処理

Noneでは、イベントハンドラーを登録していないので、このイベントハンドラーが呼ばれることはないですが、念のため、Noneの場合は、何もせず制御を戻します。

MoveFocusの処理

FrameworkElement.MoveFocus()を呼び出して、フォーカスを移動します。Enterキー単独の場合は次の要素にフォーカスを移動します。EnterキーがShiftキーの組み合わせの場合は、前の要素にフォーカスを移動します。この処理は、フォーカスが他の要素に移ってしまうため、一番最後に処理します。

UpdateSourceの処理

TextBox.TextのBindingExpressionを取得し、バインディングソースの値を更新します。

SelectAllの処理

TextBox.SelectAll()を呼び出して、すべてのテキスト選択します。

nugetライブラリー化

今回、この添付プロパティを容易に利用できるようにするため、nugetライブラリー化しました。

nuget.orgに、NishySoftware.Wpf.AttachedProperties (nsAttachedProperties)として公開しました。パッケージを参照したら、すぐに利用できるようになります。

TextBoxへの設定

xaml上では、TextBoxでEnterキーが押されたときの挙動を制御するために、以下のように利用します。

<Window
  ...
  xmlns:nsAttachedProps="http://schemas.nishy-software.com/xaml/attached-properties">
    <Grid>
...
      <TextBox
          Text="{Binding TextValue}"
          nsAttachedProps:TextBoxProperties.ReturnBehavior="UpdateSource"/>
...
</Window>

以上、今回の投稿では、

  • TextBoxでEnterキーを押したときの挙動を拡張するための添付プロパティの設計
  • それをライブラリー化したnugetパッケージ NishySoftware.Wpf.AttachedProperties (nsAttachedProperties)の公開

について説明しました。

“WPFのTextBoxのEnterキーの挙動の変更♯2” への1件の返信

コメントを残す