在WPF中转到Enter keypress上的下一个控件

Kis*_*mar 34 c# wpf mvvm

当我在WPF MVVM应用程序中按Enter键而不是Tab键时,我想转到下一个控件.我怎样才能做到这一点?

Jay*_*Jay 42

以下是我用过的附属物.

一,示例用法:

<TextBox Width="100"
         Text="{Binding Name, Mode=TwoWay}"
         UI:FocusAdvancement.AdvancesByEnterKey="True" />
Run Code Online (Sandbox Code Playgroud)

(UI是我定义以下内容的命名空间别名.)

附属物:

public static class FocusAdvancement
{
    public static bool GetAdvancesByEnterKey(DependencyObject obj)
    {
        return (bool)obj.GetValue(AdvancesByEnterKeyProperty);
    }

    public static void SetAdvancesByEnterKey(DependencyObject obj, bool value)
    {
        obj.SetValue(AdvancesByEnterKeyProperty, value);
    }

    public static readonly DependencyProperty AdvancesByEnterKeyProperty =
        DependencyProperty.RegisterAttached("AdvancesByEnterKey", typeof(bool), typeof(FocusAdvancement), 
        new UIPropertyMetadata(OnAdvancesByEnterKeyPropertyChanged));

    static void OnAdvancesByEnterKeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var element = d as UIElement;
        if(element == null) return;

        if ((bool)e.NewValue) element.KeyDown += Keydown;
        else element.KeyDown -= Keydown;
    }

    static void Keydown(object sender, KeyEventArgs e)
    {
        if(!e.Key.Equals(Key.Enter)) return;

        var element = sender as UIElement;
        if(element != null) element.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
    }
}
Run Code Online (Sandbox Code Playgroud)

你还说"而不是tab",所以我想知道你是否想要抑制以通常的方式使用tab的能力.我建议反对它,因为它是一个常见的,众所周知的范例,但如果是这种情况,你可以PreviewKeyDown在附加属性中添加一个处理程序,检查tab键,并Handled = true为事件args 设置.


Sti*_*nin 29

如果你只想让它适用于几个文本框,Jay的答案是最好的.

如果你希望你的整个应用程序以这种方式工作,makwana.a的答案会更好,但可以改进.

下面是我对makwana.a的答案的修改,我已经在很多应用程序中使用过它.如果活动控件是复选框,它还包括通过输入移动到下一个控件的支持.我没有使用tag属性来决定焦点是否应该移动,而是使用AcceptsReturn了文本框的属性.我这样做是因为它默认为false,并且只会在多行文本框中设置为true.在这种情况下,您无论如何都不希望焦点移动到下一个控件上.

在OnStartup void App.xaml中声明这些事件处理程序

        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));
        EventManager.RegisterClassHandler(typeof(CheckBox), CheckBox.KeyDownEvent, new KeyEventHandler(CheckBox_KeyDown));
Run Code Online (Sandbox Code Playgroud)

以下是使其适用于应用程序所需的其他方法.

    void TextBox_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter & (sender as TextBox).AcceptsReturn == false) MoveToNextUIElement(e);
    }

    void CheckBox_KeyDown(object sender, KeyEventArgs e)
    {
        MoveToNextUIElement(e);
        //Sucessfully moved on and marked key as handled.
        //Toggle check box since the key was handled and
        //the checkbox will never receive it.
        if (e.Handled == true)
        {
            CheckBox cb = (CheckBox)sender;
            cb.IsChecked = !cb.IsChecked;
        }

     }

    void MoveToNextUIElement(KeyEventArgs e)
    {
        // Creating a FocusNavigationDirection object and setting it to a
        // local field that contains the direction selected.
        FocusNavigationDirection focusDirection = FocusNavigationDirection.Next;

        // MoveFocus takes a TraveralReqest as its argument.
        TraversalRequest request = new TraversalRequest(focusDirection);

        // Gets the element with keyboard focus.
        UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

        // Change keyboard focus.
        if (elementWithFocus != null)
        {
            if (elementWithFocus.MoveFocus(request)) e.Handled = true;
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑

我更新了代码,以便在移动成功时将按键标记为已处理,并且还会切换复选框,因为密钥已处理并且将不再到达.

  • 周杰伦的答案是您在整个申请中的工作.只需在TextBox控件模板中设置附加属性,它们都可以按需运行. (4认同)

Pau*_*ich 14

示例解决方案:在堆栈面板中使用PreviewKeyDown.预览...是一个泡沫,因此可以在更高级别处理事件.对于不同的元素类型,您可能需要以不同的方式处理它,例如按钮似乎应该保持回车键而不是将注意力更改为回车键.

这是xaml:

<StackPanel PreviewKeyDown="StackPanel_PreviewKeyDown" >
    <TextBox >
        Hello
    </TextBox>
    <TextBox>
        World
    </TextBox>
    <TextBox>
        test
    </TextBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

以下是代码背后的代码:

private void StackPanel_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        TextBox s = e.Source as TextBox;
        if (s != null)
        {
            s.MoveFocus(new TraversalRequest( FocusNavigationDirection.Next));
        }

        e.Handled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

这只是一个用于概念验证的沙箱.

快乐编码......