Passer au contrôle suivant sur Entrer dans keypress dans WPF

je veux passer au contrôle suivant lorsque j'appuie sur la touche Enter au lieu de la touche Tab dans une application MVVM WPF. Comment puis-je y parvenir?

28
demandé sur bobbymcr 2011-11-20 21:35:19

7 réponses

la réponse de Jay est agréable si vous voulez que cela fonctionne seulement pour quelques boîtes de texte, mais si vous voulez que toute votre application fonctionne de cette façon, je favorise certainement makwana.une réponse de l'. Voici ma modification de makwana.une réponse qui, je l'utiliser en C#. J'ai également inclus le support pour passer à la commande suivante via enter si la commande active est une case à cocher.

notez aussi Qu'au lieu d'utiliser la propriété tag pour indiquer si oui ou non le focus doit être déplacé, j'utilise L'AcceptsReturn propriété de la boîte de texte car il est par défaut à false et vous ne le définirez à true que sur les boîtes de texte que vous voulez utiliser comme multi-ligne c.-à-d. qui ne devrait pas se concentrer sur Entrée clé.

déclarer ces gestionnaires d'événements dans L'OnStartup sans App.xaml

        EventManager.RegisterClassHandler(typeof(TextBox), TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));
        EventManager.RegisterClassHandler(typeof(CheckBox), CheckBox.KeyDownEvent, new KeyEventHandler(CheckBox_KeyDown));

Voici le reste des méthodes nécessaires pour faire fonctionner l'application de large.

    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;
        }
    }

Modifier

j'ai mis à jour le code pour marquer la touche comme manipulé si le mouvement a été un succès et aussi basculer la case à cocher depuis que la clé a été manipulée et ne sera plus l'atteindre.

24
répondu StillLearnin 2012-10-31 21:30:17

ci-dessous est une propriété attachée que j'ai utilisé pour ceci.

tout d'Abord, exemple d'utilisation:

<TextBox Width="100"
         Text="{Binding Name, Mode=TwoWay}"
         UI:FocusAdvancement.AdvancesByEnterKey="True" />

(UI est l'alias du namespace pour lequel j'ai défini ce qui suit.)

La propriété attachée:

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));
    }
}

vous avez aussi dit" au lieu de tab", donc je me demande si vous voulez supprimer la capacité d'utiliser tab de la manière habituelle. Je vous le déconseille, car il est un bien commun, bien connu de paradigme, mais si c'est le cas, vous pouvez ajouter un PreviewKeyDown handler dans la propriété ci-jointe, vérifiez la touche tab, et mettez Handled = true pour l'événement args.

39
répondu Jay 2011-11-20 19:57:15

exemple de solution: utilisation de PreviewKeyDown dans le panneau de la pile. aperçu... est une bulle de sorte que les cas peuvent être traités à un niveau supérieur. Vous pouvez avoir besoin de gérer cela différemment pour les différents types d'éléments, comme bouton, il semble devrait garder la touche enter et ne pas changer de focus sur la touche enter.

Voici le code xaml:

<StackPanel PreviewKeyDown="StackPanel_PreviewKeyDown" >
    <TextBox >
        Hello
    </TextBox>
    <TextBox>
        World
    </TextBox>
    <TextBox>
        test
    </TextBox>
</StackPanel>

Et voici le code derrière:

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;
    }
}

ce n'est qu'un bac à sable pour la validation de principe.

Heureux Codage...

11
répondu Paul Matovich 2011-11-20 19:39:48

ecrire ce code dans l'evenement onstartup de votre fichier d'application

EventManager.RegisterClassHandler(GetType(TextBox), TextBox.KeyDownEvent, New RoutedEventHandler(AddressOf TextBox_KeyDown))

puis Définir TextBox_KeyDown sub comme

 Private Sub TextBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs)
    If e.Key = Key.Enter And TryCast(sender, TextBox).Tag <> "1" Then
        ' Creating a FocusNavigationDirection object and setting it to a
        ' local field that contains the direction selected.
        Dim focusDirection As FocusNavigationDirection = FocusNavigationDirection.Next

        ' MoveFocus takes a TraveralReqest as its argument.
        Dim request As New TraversalRequest(focusDirection)

        ' Gets the element with keyboard focus.
        Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)

        ' Change keyboard focus.
        If elementWithFocus IsNot Nothing Then
            elementWithFocus.MoveFocus(request)
        End If
    End If
End Sub

j'ai utilisé la propriété "tag" de textbox pour skip move focus. c'est-à-dire si vous ne voulez pas passer à la commande suivante sur la touche enter pressée (dans le cas de la boîte de texte multiligne où enter est nécessaire pour créer une nouvelle ligne). Il suffit de mettre la propriété tag à 1.

3
répondu makwana.a 2015-06-05 07:37:48

espérer cette aide: utilisez la propriété jointe http://madprops.org/blog/enter-to-tab-as-an-attached-property/

public class EnterKeyTraversal
{
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }

    static void ue_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
    {
        var ue = e.OriginalSource as FrameworkElement;

        if (e.Key == Key.Enter)
        {
            e.Handled = true;
            ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
    }

    private static void ue_Unloaded(object sender, RoutedEventArgs e)
    {
        var ue = sender as FrameworkElement;
        if (ue == null) return;

        ue.Unloaded -= ue_Unloaded;
        ue.PreviewKeyDown -= ue_PreviewKeyDown;
    }

    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
        typeof(EnterKeyTraversal), new UIPropertyMetadata(false, IsEnabledChanged));

    static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ue = d as FrameworkElement;
        if (ue == null) return;

        if ((bool)e.NewValue)
        {
            ue.Unloaded += ue_Unloaded;
            ue.PreviewKeyDown += ue_PreviewKeyDown;
        }
        else
        {
            ue.PreviewKeyDown -= ue_PreviewKeyDown;
        }
    }
}

<StackPanel my:EnterKeyTraversal.IsEnabled="True">
2
répondu MasterLuV 2018-01-30 06:55:13

le Premier qui s'est produit à ajouter de déclenchement pour chaque élément qui invoque quand PreviewKeyDown les incendies. Ajoutez aussi la propriété de dépendance et bind FrameworkElement que vous avez l'habitude d'attirer l'attention. Au sein de déclencher fournir la configuration de Focus à l'élément lié.

1
répondu Anatolii Gabuza 2011-11-20 18:51:21

à l'Aide de code-behind:

je suis venu avec le code ci-dessous. Notez qu'il n'est pas ensemble e.Manipulés. En outre, MoveFocus_Next ne renvoie pas si la mise au point du mouvement a été réussie, mais plutôt si l'argument n'est pas null. Vous pouvez ajouter ou supprimer des types de commandes à manipuler au besoin. Le code a été écrit pour le MainWindow de l'application, mais traite d'autres fenêtres aussi bien. Vous pouvez également adapter le code pour l'invocation à partir de L'événement App_Startup.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

public partial class MainWindow : Window
{
    private bool MoveFocus_Next(UIElement uiElement)
    {
        if (uiElement != null)
        {
            uiElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            return true;
        }
        return false;
    }

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(Window_PreviewKeyUp));
    }

    private void Window_PreviewKeyUp(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            IInputElement inputElement = Keyboard.FocusedElement;
            if (inputElement != null)
            {
                System.Windows.Controls.Primitives.TextBoxBase textBoxBase = inputElement as System.Windows.Controls.Primitives.TextBoxBase;
                if (textBoxBase != null)
                {
                    if (!textBoxBase.AcceptsReturn)
                        MoveFocus_Next(textBoxBase);
                    return;
                }
                if (
                    MoveFocus_Next(inputElement as ComboBox)
                    ||
                    MoveFocus_Next(inputElement as Button)
                    ||
                    MoveFocus_Next(inputElement as DatePicker)
                    ||
                    MoveFocus_Next(inputElement as CheckBox)
                    ||
                    MoveFocus_Next(inputElement as DataGrid)
                    ||
                    MoveFocus_Next(inputElement as TabItem)
                    ||
                    MoveFocus_Next(inputElement as RadioButton)
                    ||
                    MoveFocus_Next(inputElement as ListBox)
                    ||
                    MoveFocus_Next(inputElement as ListView)
                    ||
                    MoveFocus_Next(inputElement as PasswordBox)
                    ||
                    MoveFocus_Next(inputElement as Window)
                    ||
                    MoveFocus_Next(inputElement as Page)
                    ||
                    MoveFocus_Next(inputElement as Frame)
                )
                    return;
            }
        }
    }
}
0
répondu Thejaka Maldeniya 2014-02-05 09:36:27