IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

WPF, MVVM : Comment passer automatiquement d'un champ à l'autre avec la touche Entrée [Débutant]


Sujet :

Windows Presentation Foundation

  1. #1
    Membre à l'essai
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Novembre 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2012
    Messages : 20
    Points : 17
    Points
    17
    Par défaut WPF, MVVM : Comment passer automatiquement d'un champ à l'autre avec la touche Entrée
    Bonjour tout le monde,

    J'utilise le framework MVVM Light pour développer une petite application avec WPF selon le pattern MVVM .
    Je voudrais passer automatiquement le focus d'un TextBox au suivant juste en appuyant sur la touche ENTREE du clavier.
    Je sais comment intercepter la touche entrée (le framework MVVM Light offre le convertisseur EventToCommand qui convertit un évènement en une Commande ), mais mon problème réside dans le fait que je n'arrive pas à faire passer le focus au TextBox suivant.

    Merci.

  2. #2
    Membre à l'essai
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Novembre 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2012
    Messages : 20
    Points : 17
    Points
    17
    Par défaut J'ai trouvé une solution
    Bonjour tout le monde,

    J'ai trouvé une solution mais je ne sais pas si elle respecte bien les règles de MVVM ou non. En effet, voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    <Window x:Class="WpfMMVLight2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
            xmlns:cmd ="http://www.galasoft.ch/mvvmlight"
            Title="MainWindow" Height="350" Width="525"
            DataContext="{Binding MainViewModel}">
        <Grid FocusManager.FocusedElement="{Binding ElementName=tb1}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="70"/>
            </Grid.ColumnDefinitions>
     
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
     
            <TextBlock Grid.Column="0" Text="Text 1" VerticalAlignment="Center"/>
            <TextBox x:Name="tb1" Grid.Column="1" VerticalAlignment="Center" Margin="5">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="KeyDown">
                        <cmd:EventToCommand PassEventArgsToCommand="True"
                                                       Command ="{Binding KeyDownCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
     
     
            <TextBlock Grid.Column="0" Grid.Row="1" Text="Text 2" VerticalAlignment="Center"/>
            <TextBox x:Name="tb2" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Margin="5">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="KeyDown">
                        <cmd:EventToCommand PassEventArgsToCommand="True"
                                                       Command ="{Binding KeyDownCommand, Mode=OneWay}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
     
        </Grid>
    </Window>
    et dans le view modèle :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
     private ICommand _keydownCommand;
     public ICommand KeyDownCommand
            {
               get
                {
                    if (_keydownCommand== null)
                        _keydownCommand= new DelegateCommand<KeyEventArgs>(KeyDownCommandExecute);
                    return _keydownCommand;
                }
     
     
     
            }
     
     
            private void KeyDownCommandExecute(KeyEventArgs e)
            {
                if (e != null && e.Key == Key.Enter)
                {
                    TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
                    request.Wrapped = true;
                    ((Control)e.Source).MoveFocus(request);
                }
     
     
            }
        }
    Je ne sais pas si l'utilisation des classe visuelles tel que Control est permi dans le View Model ou non ?

  3. #3
    Membre averti
    Avatar de SoBaKa
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 242
    Points : 349
    Points
    349
    Par défaut
    Bonjour,

    Pourquoi le ViewModel devrait-il gérer le focus des éléments? Cela fait partie de la vue et devrait dans le meilleur des cas le rester.

    Dans ce cas la, plusieurs solutions existent, par exemple :
    - Créer tes propres contrôles qui héritent des contrôles "originaux"... ok c'est loin d'être la bonne solution
    - Créer un Behavior qui va pouvoir adapter le comportement de certains contrôles... bien

    Pour créer le "behavior", on a besoin de System.Windows.Interactivity.WPF qui est bien évidemment retrouvable sur nuget et qui vient du SDK de blend.

    En regardant le code ci-dessous, on peut voir que je fais un "behavior" pour tous les objets de type UIElement.

    Code CS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    internal class FocusNextOnEnterBehavior : Behavior<UIElement>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
     
            AssociatedObject.PreviewKeyDown += (obj, e) =>
            {
                TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
                request.Wrapped = true;
                AssociatedObject.MoveFocus(request);
            };
        }
    }

    Niveau utilisation, coté XAML, on références les namespace :

    Code XAML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:b="clr-namespace:DemoFocus.Behaviors"

    Et ensuite on peut l'utiliser sur nos contrôles :

    Code XAML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <TextBox Text="" Width="200" Margin="10">
        <i:Interaction.Behaviors>
            <b:FocusNextOnEnterBehavior />
        </i:Interaction.Behaviors>
    </TextBox>
     
    <ComboBox Width="200" Margin="10">
        <i:Interaction.Behaviors>
            <b:FocusNextOnEnterBehavior />
        </i:Interaction.Behaviors>
        <ComboBox.Items>
            <ComboBoxItem Content="1" />
            <ComboBoxItem Content="2" />
            <ComboBoxItem Content="3" />
        </ComboBox.Items>
    </ComboBox>

    Voilà, j'espère que cette solution te convient.
    ****** Analyse/Développeur .Net

  4. #4
    Membre à l'essai
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Novembre 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2012
    Messages : 20
    Points : 17
    Points
    17
    Par défaut Résolu
    Bonjour,

    Merci de ta réponse, ça marche à merveille. Je dois juste ajuster le "Behavior" comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    internal class FocusNextOnEnterBehavior : Behavior<UIElement>
        {
            protected override void OnAttached()
            {
                base.OnAttached();
     
                AssociatedObject.PreviewKeyDown += (obj, e) =>
                {
                    if (e.Key == Key.Enter)
                    {
                        TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
                        request.Wrapped = true;
                        AssociatedObject.MoveFocus(request);
                    }
                };
            }
     
     protected override void OnDetaching()
      {
        AssociatedObject.PreviewKeyDown -= AssociatedObject_PreviewKeyDown;
      }
        }
    Car je veux qu'uniquement la touche Entrée fera passer le focus au contrôle suivant et ainsi en n'oubliant pas de retirer le gestionnaire lors de détachement.

    Merci beaucoup.

  5. #5
    Membre averti
    Avatar de SoBaKa
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 242
    Points : 349
    Points
    349
    Par défaut
    Effectivement, j'allais quand même pas donné la réponse correcte!

    Bon j'avoue... c'était un oubli dans le code pour la touche "Enter"
    ****** Analyse/Développeur .Net

  6. #6
    Membre à l'essai
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Novembre 2012
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2012
    Messages : 20
    Points : 17
    Points
    17
    Par défaut N'oublis pas de retirer le gestionnaire PreviewKeyDown lors du détachement
    Citation Envoyé par SoBaKa Voir le message
    Effectivement, j'allais quand même pas donné la réponse correcte!

    Bon j'avoue... c'était un oubli dans le code pour la touche "Enter"
    N'oublis pas de retirer le gestionnaire PreviewKeyDown lors du détachement.

    Donc ici on est obligé de nommer le gestionnaire puis ce qu'on aura besoin de son nom pour le retirer lors de détachement, le code de la classe devient alors :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    internal class FocusNextOnEnterBehavior : Behavior<UIElement>
        {
    protected override void OnAttached()
      {
        AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown;
      }
     
      private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
      {
        if (e.Key == Key.Enter)
        {
          var request = new TraversalRequest(FocusNavigationDirection.Next);
          request.Wrapped = true;
          AssociatedObject.MoveFocus(request);
        }
      }
     
      protected override void OnDetaching()
      {
        AssociatedObject.PreviewKeyDown -= AssociatedObject_PreviewKeyDown;
      }
    }

    C'est une solution élégante et clean, un très grand merci et au revoir.

  7. #7
    Membre averti
    Avatar de SoBaKa
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2006
    Messages : 242
    Points : 349
    Points
    349
    Par défaut
    Citation Envoyé par intibnin Voir le message
    N'oublis pas de retirer le gestionnaire PreviewKeyDown lors du détachement.
    Cela dépend... fait un point sur la méthode "Detaching". Que se passe-t-il? Il ne passe pas dans cette méthode. Tout simplement car il n'y a pas d'appel à la méthode "Detach()" du Behavior.
    ****** Analyse/Développeur .Net

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD18] Basculer entre les Champs de saisie avec la touche entrée
    Par charifclub dans le forum WinDev
    Réponses: 5
    Dernier message: 07/10/2013, 15h32
  2. Réponses: 2
    Dernier message: 29/01/2010, 12h06
  3. Réponses: 4
    Dernier message: 18/10/2007, 15h16
  4. Réponses: 3
    Dernier message: 04/06/2007, 11h51
  5. [JavaScript] [FAQ][correction] Comment passer automatiquement au champ suivant
    Par Auteur dans le forum Contribuez
    Réponses: 10
    Dernier message: 14/12/2006, 18h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo