2

CheckBox、TextBlock、および TextBox を含むカスタム データ テンプレートを含む ListBox があります。通常、ListBox 内の項目を選択すると、実際には基になる ListBoxItem にフォーカスがあるため、上下のキーに反応します。さらに、CheckBox にフォーカスがある場合、上下のキー自体には何もしないため、喜んでそれらを無視し、基礎となる ListBoxItem によっても処理されます。ここまでは順調です。

ただし、TextBox には上下のキーに対する独自の処理規則があり、キャレットをテキスト内の 1 行上または下に名前を付けて移動します。そのため、TextBox にフォーカスがある場合、上下のキーは ListBox の選択のナビゲーションを壊し、編集にも役立ちません。

ここで、PreviewKeyDownEvent を処理し (以下で行いますが、理由は異なります)、押されたキーに応じて動作を手動で処理できますが、これは非常に具体的な解決策であり、コントロールがコンテナーの動作を認識している必要があります。

完璧な世界 (および疑似コード) では、 MyTextBox.KeysToIgnore(Up, Down) または同様のことを言って、それを実行させたいと思います...それらのキーは、存在しないかのように無視します。(繰り返しますが、飲み込むのではなく、無視して通過させます。)

しかし、それまでは、これが私が思いついたものです。これは機能しているように見えますが、私にはとても「ハック」に見えます...

private void PreviewKeyDownHandler(object sender, KeyEventArgs e) {

    switch (e.Key){
        case Key.Up:
        case Key.Down:
        case Key.OtherKeyToIgnore
        case Key.AndAnother

            e.Handled = true;

            FrameworkElement target = VisualTreeHelper.GetParent(
                e.Source as DependencyObject) as FrameworkElement;

            target.RaiseEvent(
                new KeyEventArgs(
                    e.KeyboardDevice,
                    PresentationSource.FromVisual(target),
                    0,
                    e.Key
                ){
                    RoutedEvent=Keyboard.KeyDownEvent
                }
            );
            break;

    }

}

これには、PreviewKeyDown イベントをターゲットに送信しないという欠点もあります。これを回避して、最初にそのイベントを送信し、実際の KeyDown メッセージを送信する前に e.Handled を確認することで偽装することができます。 .上記で処理したように、偽のイベントをいつ送信するかを知るために、本当の「キーアップ」イベントを取得することはありません。さらに、通常の非プレビュー バージョンとは逆方向にバブルするため、PreviewKeyxxx メッセージの方向性も破ることになると確信しています。(たぶん内部で処理されていると思いますが、そうではないと思います。)

私が言ったように...ハッキー、ハッキー、ハッキー!

しかし、それは機能するので、それがあります。そして、これを Attached Behaviors を介して実装できるため、このルートに行きました。(添付されたビヘイビアーの実装では、これは case ステートメントではなく、XAML で指定したキーのコレクションに対するチェックです。) 必要な他のすべてのビヘイビアーを失うという考えは好きではありません。

繰り返しますが、「Hey TextBox... 上または下のキーが押されているのを見たら、STFU ya b*stard!!」と言いたいだけです。それ以外の場合は、キーを透過的にします。

誰か考えますか?

4

2 に答える 2

1

ええ、TextBoxのキーイベント処理は確かにあなたに頭痛の種を与える可能性があります。問題は、EventManager.RegisterClassEventHandlerを介して登録されたコールバックの呼び出し順序を判別できないことです。つまり、コールバックが未処理のイベントで呼び出され、次にイベントが処理されます。これで、TextBoxをサブクラス化し、コンストラクターで「AddEventHandler(KeyDownEvent、callback、true)」を呼び出すことで、キーイベントを「未処理」にする方法を見つけました。次に、状況に応じてe.Handled=falseを設定します。イベントがTextBoxによって処理された後、コールバックが呼び出されるようです。クラスごとに1つのデリゲートインスタンスを作成するのではなく、TextBoxのインスタンスごとにデリゲートのインスタンスを作成するのは非常に便利ではありませんが、他の回避策はありません。

于 2010-11-30T12:49:58.977 に答える
1

男...コメントは1つもありません。ほぼ1か月で回答は言うまでもありません。まあ...上記の私の「ハック」ソリューションがこれを行う方法だと思うので、これを答えとしてマークしています。

于 2010-11-10T06:01:48.110 に答える