205 votes

WPF et focus initial

Il semble que quand une application WPF commence, rien n'a le focus.

C'est vraiment bizarre. Tout autre cadre que j'ai utilisé ne fonctionne tout simplement ce que vous attendez: met d'abord l'accent sur le premier dans l'ordre de tabulation. Mais j'ai confirmé que c'est WPF, pas juste mon app-si-je créer une nouvelle Fenêtre, et il suffit de mettre une zone de texte, et à exécuter l'application, la zone de texte n'a pas le focus jusqu'à ce que j'cliquez sur ou appuyez sur l'Onglet. Beurk.

Mon application est plus compliqué que juste une zone de texte. J'ai plusieurs couches de UserControls dans UserControls. L'un de ces contrôles utilisateur a Focusable="True" et KeyDown/KeyUp gestionnaires, et je veux qu'il ait le focus dès que ma fenêtre s'ouvre. Je suis toujours un peu de WPF novice, et je ne suis pas du avoir beaucoup de chance de trouver comment le faire.

Si je commence mon application et appuyez sur la touche Tab, la priorité va à mon focusable de contrôle, et il commence à travailler comme je le veux. Mais je ne veux pas que mes utilisateurs doivent cliquer sur l'Onglet avant qu'ils puissent commencer à l'aide de la fenêtre.

J'ai joué avec FocusManager.FocusedElement, mais je ne suis pas sûr de contrôler le (la Fenêtre de niveau supérieur? le parent qui contient les focusable de contrôle? le focusable le contrôle de lui-même?) ou ce pour le régler.

Que dois-je faire pour obtenir mon profondément imbriquée contrôle pour avoir le point initial dès que la fenêtre s'ouvre? Ou mieux encore, à l'accent de la première focusable de contrôle dans l'ordre de tabulation?

182voto

Sean Points 381

Cela fonctionne aussi:

 FocusManager.FocusedElement="{Binding ElementName=*name of control*}"
 

167voto

Joe White Points 32629

J'ai eu la bonne idée de fouiller dans Reflector pour voir où la propriété Focusable est utilisée, et j'ai trouvé la voie vers cette solution. Je dois juste ajouter le code suivant au constructeur de ma fenêtre:

 Loaded += (sender, e) =>
    MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
 

Cela sélectionnera automatiquement le premier contrôle dans l'ordre de tabulation, c'est donc une solution générale qui devrait pouvoir être placée dans n'importe quelle fenêtre et fonctionner.

64voto

Mizipzor Points 10952

Basé sur la réponse acceptée implémentée en tant que comportement associé:

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

namespace UI.Behaviors
{
    public static class FocusBehavior
    {
        public static readonly DependencyProperty FocusFirstProperty =
            DependencyProperty.RegisterAttached(
                "FocusFirst",
                typeof(bool),
                typeof(Control),
                new PropertyMetadata(false, OnFocusFirstPropertyChanged));

        public static bool GetFocusFirst(Control control)
        {
            return (bool)control.GetValue(FocusFirstProperty);
        }

        public static void SetFocusFirst (Control control, bool value)
        {
            control.SetValue(FocusFirstProperty, value);
        }

        static void OnFocusFirstPropertyChanged(
            DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            Control control = obj as Control;
            if (control == null || !(args.NewValue is bool))
            {
                return;
            }

            if ((bool)args.NewValue)
            {
                control.Loaded += (sender, e) =>
                    control.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
            }
        }
    }
}
 

Utilisez-le comme ceci:

 <Window xmlns:Behaviors="clr-namespace:UI.Behaviors"
        Behaviors:FocusBehavior.FocusFirst="true">
 

14voto

Joe White Points 32629

J'ai trouvé une autre solution possible. Mark Smith a publié une extension de balisage FirstFocusedElement à utiliser avec FocusManager.FocusedElement.

 <UserControl x:Class="FocusTest.Page2"
    xmlns:FocusTest="clr-namespace:FocusTest"
    FocusManager.FocusedElement="{FocusTest:FirstFocusedElement}">
 

9voto

Vladik Y Points 71

Avait le même problème résolu avec une solution simple: Dans la fenêtre principale:

   <Window ....
        FocusManager.FocusedElement="{Binding ElementName=usercontrolelementname}"
         ... />
 

Dans le contrôle utilisateur:

 private void UserControl_GotFocus_1(object sender, RoutedEventArgs e)
        {
            targetcontrol.Focus();
            this.GotFocus -= UserControl_GotFocus_1;  // to set focus only once
        }
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X