24

以下の状況。5 つのキーバインドを持つ UserControl があります。TextBox にフォーカスがある場合、UserControl のキーバインドは起動を停止します。

この「問題」を解決する方法はありますか?

<UserControl.InputBindings>
    <KeyBinding Key="PageDown" Modifiers="Control" Command="{Binding NextCommand}"></KeyBinding>
    <KeyBinding Key="PageUp" Modifiers="Control" Command="{Binding PreviousCommand}"></KeyBinding>
    <KeyBinding Key="End" Modifiers="Control"  Command="{Binding LastCommand}"></KeyBinding>
    <KeyBinding Key="Home" Modifiers="Control" Command="{Binding FirstCommand}"></KeyBinding>
    <KeyBinding Key="F" Modifiers="Control" Command="{Binding SetFocusCommand}"></KeyBinding>
</UserControl.InputBindings>
<TextBox Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding Gesture="Enter" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl }}, Path=DataContext.FilterCommand}"></KeyBinding>
    </TextBox.InputBindings>
</TextBox>

ファンクションキー ( F1etc) とALT+が機能するよう[key]です。CTRL修飾子とSHIFT修飾子が何らかの形でイベントが UserControl にバブリングするのを「ブロック」していると思います。

4

5 に答える 5

54

一部の入力バインディングが機能し、一部が機能しない理由は、TextBox コントロールが一部のキー バインディングをキャッチして処理するためです。たとえば、貼り付け用の+ 、テキストの先頭に移動するためのCTRL+などを処理します。一方、 +などの他のキーの組み合わせは、TextBox によって処理されないため、バブルアップします。VCTRLHomeCTRLF3

TextBox の入力バインディングを無効にしたいだけなら、それは簡単ApplicationCommands.NotACommandです。デフォルトの動作を無効にするコマンドを使用できます。たとえば、次の場合、CTRL+による貼り付けはV無効になります。

<TextBox>
    <TextBox.InputBindings>
        <KeyBinding Key="V" Modifiers="Control" Command="ApplicationCommands.NotACommand" />
    </TextBox.InputBindings>
</TextBox>

ただし、ユーザー コントロールにバブルアップさせるのは少し面倒です。私の提案は、UserControl に適用されるアタッチされた動作を作成し、そのPreviewKeyDownイベントに登録し、TextBox に到達する前に必要に応じて入力バインディングを実行することです。これにより、入力バインディングが実行されるときに UserControl が優先されます。

開始するために、この機能を実現する基本的な動作を書きました。

public class InputBindingsBehavior
{
    public static readonly DependencyProperty TakesInputBindingPrecedenceProperty =
        DependencyProperty.RegisterAttached("TakesInputBindingPrecedence", typeof(bool), typeof(InputBindingsBehavior), new UIPropertyMetadata(false, OnTakesInputBindingPrecedenceChanged));

    public static bool GetTakesInputBindingPrecedence(UIElement obj)
    {
        return (bool)obj.GetValue(TakesInputBindingPrecedenceProperty);
    }

    public static void SetTakesInputBindingPrecedence(UIElement obj, bool value)
    {
        obj.SetValue(TakesInputBindingPrecedenceProperty, value);
    }

    private static void OnTakesInputBindingPrecedenceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((UIElement)d).PreviewKeyDown += new KeyEventHandler(InputBindingsBehavior_PreviewKeyDown);
    }

    private static void InputBindingsBehavior_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        var uielement = (UIElement)sender;

        var foundBinding = uielement.InputBindings
            .OfType<KeyBinding>()
            .FirstOrDefault(kb => kb.Key == e.Key && kb.Modifiers == e.KeyboardDevice.Modifiers);

        if (foundBinding != null)
        {
            e.Handled = true;
            if (foundBinding.Command.CanExecute(foundBinding.CommandParameter))
            {
                foundBinding.Command.Execute(foundBinding.CommandParameter);
            }
        }
    }
}

使用法:

<UserControl local:InputBindingsBehavior.TakesInputBindingPrecedence="True">
    <UserControl.InputBindings>
        <KeyBinding Key="Home" Modifiers="Control" Command="{Binding MyCommand}" />
    </UserControl.InputBindings>
    <TextBox ... />
</UserControl>

お役に立てれば。

于 2012-10-17T21:02:17.137 に答える
4

Adi Lester のソリューションはうまく機能します。Behavior を使用した同様のソリューションを次に示します。C# コード:

public class AcceptKeyBinding : Behavior<UIElement>
{


    private TextBox _textBox;



    /// <summary>
    ///  Subscribes to the PreviewKeyDown event of the <see cref="TextBox"/>.
    /// </summary>
    protected override void OnAttached()
    {
        base.OnAttached();

        _textBox = AssociatedObject as TextBox;

        if (_textBox == null)
        {
            return;
        }

        _textBox.PreviewKeyDown += TextBoxOnPreviewKeyDown;
    }

    private void TextBoxOnPreviewKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        var uielement = (UIElement)sender;

        var foundBinding = uielement.InputBindings
            .OfType<KeyBinding>()
            .FirstOrDefault(kb => kb.Key == keyEventArgs.Key && kb.Modifiers ==           keyEventArgs.KeyboardDevice.Modifiers);

        if (foundBinding != null)
        {
            keyEventArgs.Handled = true;
            if (foundBinding.Command.CanExecute(foundBinding.CommandParameter))
            {
                foundBinding.Command.Execute(foundBinding.CommandParameter);
            }
        }
    }

    /// <summary>
    ///     Unsubscribes to the PreviewKeyDown event of the <see cref="TextBox"/>.
    /// </summary>
    protected override void OnDetaching()
    {
        if (_textBox == null)
        {
            return;
        }

        _textBox.PreviewKeyDown -= TextBoxOnPreviewKeyDown;

        base.OnDetaching();
    }

}

そしてXAML:

<TextBox>
  <TextBox.InputBindings>
      <KeyBinding Key="Enter" Modifiers="Shift" Command="{Binding CommandManager[ExecuteCommand]}"
          CommandParameter="{Binding ExecuteText}" />
  </TextBox.InputBindings>
      <i:Interaction.Behaviors>
         <behaviours:AcceptKeyBinding />
      </i:Interaction.Behaviors>
</TextBox>
于 2014-05-02T02:14:18.343 に答える
0
<UserControl.Style>
    <Style TargetType="UserControl">
        <Style.Triggers>
            <Trigger Property="IsKeyboardFocusWithin" Value="True">
                <Setter Property="FocusManager.FocusedElement" Value="   {Binding ElementName=keyPressPlaceHoler}" />
                </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Style>

keyPressPlaceHolerターゲットのコンテナの名前ですuielement

ユーザーコントロールで設定することを忘れないFocusable="True"でください

于 2016-06-12T18:10:57.453 に答える