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 :

[MVVM][.net3.5] InputBinding, Binding Command et CommandParameter


Sujet :

Windows Presentation Foundation

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Août 2010
    Messages : 188
    Par défaut [MVVM][.net3.5] InputBinding, Binding Command et CommandParameter
    Bonjour,

    Via le lien suivant j'avais presque trouver solution a mon problème.
    http://joyfulwpf.blogspot.com/2009/0...eybinding.html

    Petite explication:
    On m'impose d'utiliser le Framework .net 3.5 et j'ai besoin d’exécuter dans mon logiciel des Command à partir d'InputBindings: KeyBinding et/ou MouseBinding.
    Hors, avec ce Framework, il est impossible de Bindé une Command (chose qui par d'ailleurs as été résolue pour le Framework .net 4.0)
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <MenuItem.InputBindings>
        <KeyBinding Modifiers="Control" Key="P" Command={Binding CommandPrint}" />
    </MenuItem.InputBindings>

    Afin d'éviter ce problème de compatibilité de Binding de Command sur un InputBinding en Framework 3.5, j'ai trouver sur le net une petite solution (le lien ci-dessus) qui utilise une class nommé CommandRéférence (à récupérer dans le sample) qui s'utilise de cette manière
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <Window.Resources>
        <coreView:CommandReference x:Key="print" Command="{Binding CommandPrint}" />
    </Window.Resources>
    <MenuItem.InputBindings>
        <KeyBinding Modifiers="Control" Key="P" Command="{StaticResource print}" />
    </MenuItem.InputBindings>
    Jusque la tout va bien.

    Sauf que mon problème, j'aimerai allez plus loin dans mon code et y attacher des CommandParameter, chose que cette classe ne permet pas.
    De plus, pour la structure MVVM de mon logiciel, j'utilise les RelayCommand (certains me diront que se n'est pas le must mais moi cela me suffit ).
    Cette classe ne comprend pas les Execute et CanExecute que j'utilise avec ces RelayCommand
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <Button Content="Print" Command="{Binding CommandDo}" CommenParameter="Print" />

    Quelqu'un aurait-il de meilleur solution a suggérer pour prendre en compte au moins les CommandParameter?

    Merci.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Salut,

    La solution que je vois est de modifier le code en y ajoutant une propriété attachée qui te servira de CommandParameter

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par h2s84 Voir le message
    La solution que je vois est de modifier le code en y ajoutant une propriété attachée qui te servira de CommandParameter
    Tu peux préciser ton idée ? Je vois pas trop comment ça va pouvoir marcher... ou alors tu mets la propriété sur le CommandReference, mais dans ce cas ça fait que le paramètre est lié à la commande et non plus au InputBinding, donc c'est pas très clean

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Tu peux préciser ton idée ? Je vois pas trop comment ça va pouvoir marcher... ou alors tu mets la propriété sur le CommandReference, mais dans ce cas ça fait que le paramètre est lié à la commande et non plus au InputBinding, donc c'est pas très clean
    Précision : je parle de la création de la propriété CommandParameter dans la classe CommandReference. Du coup je suis d'accords ce sera lié à cette dernière et pas à la classe KeyBinding Ce n'est pas ce qu'il veut ?

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Août 2010
    Messages : 188
    Par défaut
    Citation Envoyé par h2s84 Voir le message
    Du coup je suis d'accords ce sera lié à cette dernière et pas à la classe KeyBinding Ce n'est pas ce qu'il veut ?
    Pour part se serai mieux. Je ne voit pas en quoi ce ne serai pas clean de faire comme ceci:
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <Window.Resources>
        <coreView:CommandReference x:Key="print" Command="{Binding CommandDo}" CommandParameter="Print" />
    </Window.Resources>
    <MenuItem.InputBindings>
        <KeyBinding Modifiers="Control" Key="P" Command="{StaticResource print}" />
    </MenuItem.InputBindings>

    De plus, un CommandParameter dans un KeyBinding, lui non plus n'accepte pas de recevoir un élément bindé .

    Sinon j'ai essayer d'ajouter une propriété CommandParameter il as pas aimer
    Code C# : 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
    public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));
    public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandReference), new PropertyMetadata(null));
     
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }
    public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }
     
    #region ICommand Members
     
    [DebuggerStepThrough]
    public bool CanExecute()
    {
        if (Command != null)
            return Command.CanExecute(CommandParameter);
        return false;
    }
     
    public void Execute()
    {
        Command.Execute(CommandParameter);
    }

    voici le code complet d'origine
    Code C# : 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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Input;
    using System.Windows;
    using System.Diagnostics;
    //Crédit Josh Smith
     
    namespace Common.WPF.MVVMHelpers
    {
        public class CommandReference : Freezable, ICommand
        {
            public CommandReference()
            {
                // Blank
            }
     
            public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference), new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));
     
            public ICommand Command
            {
                get { return (ICommand)GetValue(CommandProperty); }
                set { SetValue(CommandProperty, value); }
            }
     
            #region ICommand Members
     
            [DebuggerStepThrough]
            public bool CanExecute(object parameter)
            {
                if (Command != null)
                    return Command.CanExecute(parameter);
                return false;
            }
     
            public void Execute(object parameter)
            {
                Command.Execute(parameter);
            }
     
            public event EventHandler CanExecuteChanged;
     
            private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                CommandReference commandReference = d as CommandReference;
                ICommand oldCommand = e.OldValue as ICommand;
                ICommand newCommand = e.NewValue as ICommand;
     
                if (oldCommand != null)
                {
                    oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;
                }
                if (newCommand != null)
                {
                    newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;
                }
            }
     
            #endregion
     
            #region Freezable
     
            protected override Freezable CreateInstanceCore()
            {
                throw new NotImplementedException();
            }
     
            #endregion
        }
    }

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Monkey56 Voir le message
    Je ne voit pas en quoi ce ne serai pas clean de faire comme ceci:
    C'est pas clean parce que si tu veux utiliser plusieurs fois la même commande avec des paramètres différents, tu es obligé de déclarer plusieurs CommandReference. C'est un peu comme si en C#, au lieu de faire une méthode Add(int x), tu faisais une méthode Add pour chaque valeur du paramètre x (Add1(), Add2(), Add3()...)

    Citation Envoyé par Monkey56 Voir le message
    De plus, un CommandParameter dans un KeyBinding, lui non plus n'accepte pas de recevoir un élément bindé .
    Bah oui, c'est bien le problème... Mais je ne vois pas de meilleure solution que celle proposée par h2s84, même si elle me parait pas très propre

    Citation Envoyé par Monkey56 Voir le message
    Sinon j'ai essayer d'ajouter une propriété CommandParameter il as pas aimer
    C'est à dire ? Perso je ne vois pas de problème dans ton code... quelle est l'erreur ?

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Août 2010
    Messages : 188
    Par défaut
    Erreur 1:
    'MonNameSpace.CommandReference' n'implémente pas le membre d'interface 'System.Windows.Input.ICommand.CanExecute(object)'
    ...\CommandReference.cs
    ligne 12
    colone 18

    Erreur 2:
    'MonNameSpace.CommandReference' n'implémente pas le membre d'interface 'System.Windows.Input.ICommand.Execute(object)'
    ...\CommandReference.cs
    ligne 12
    colone 18
    ... et je vient de penser une idée bête:
    écrire les méthode CanExecute et Execute de cette manière (une peu null car la parametre ne sera pas utilisé, mais l'erreur disparai):
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public bool CanExecute(object parameter)
    {
        if (Command != null)
            return Command.CanExecute(CommandParameter);
        return false;
    }
     
    public void Execute(object parameter)
    {
        Command.Execute(CommandParameter);
    }

    Par contre je n'ai pas le temps de tester la je suis sur autre chose ... dès que j'aurais tester, je vous tient au courant.

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Août 2010
    Messages : 188
    Par défaut
    Bon finalement j'ai mis de côté l'autre chose que je codais je n'ai pas résister longtemps...

    Donc ce petit bout de code transformer marche finalement.
    Je me retrouve donc avec du code ressemblant a ceci
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <Window.Resources>
        <coreView:CommandReference x:Key="print" Command="{Binding CommandDo}" CommandParameter="Print" />
    </Window.Resources>
    <MenuItem.InputBindings>
        <KeyBinding Modifiers="Control" Key="P" Command="{StaticResource print}" />
    </MenuItem.InputBindings>

    Est ce que cela vous semble correct que je clôture le sujet?

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Monkey56 Voir le message
    une peu null car la parametre ne sera pas utilisé
    C'est aussi pour ça que j'aime pas beaucoup cette approche : tu ignores complètement le paramètre qu'on te passe, et tu en utilises un autre à la place... Donc si tu mets un paramètre sur le KeyBinding, il ne sera pas pris en compte, ce qui peut être un peu perturbant

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Août 2010
    Messages : 188
    Par défaut
    Citation Envoyé par tomlev Voir le message
    C'est aussi pour ça que j'aime pas beaucoup cette approche : tu ignores complètement le paramètre qu'on te passe, et tu en utilises un autre à la place... Donc si tu mets un paramètre sur le KeyBinding, il ne sera pas pris en compte, ce qui peut être un peu perturbant
    Je vient d'y remédier, plus ou moins
    Code C# : 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
    public bool CanExecute(object parameter)
    {
        if (Command != null)
        {
            if(CommandParameter != null)
                return Command.CanExecute(CommandParameter);
            else
                return Command.CanExecute(parameter);
        }
        return false;
    }
     
    public void Execute(object parameter)
    {
        if (CommandParameter != null)
            Command.Execute(CommandParameter);
        else
            Command.Execute(parameter);
    }

    Si CommandParameter de la classe CommandReference n'est pas utiliser(soit null), il prendra le CommandParameter du Input Binding.

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <KeyBinding Modifiers="Control" Key="P" Command="{StaticResource print}" CommandParameter="Print" />

    Fonctionne, j'ai tester.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Monkey56 Voir le message
    Si CommandParameter de la classe CommandReference n'est pas utiliser(soit null), il prendra le CommandParameter du Input Binding.
    Bien vu

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

Discussions similaires

  1. MVVM - Binding Command / Event
    Par Pooch dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 06/01/2011, 17h35
  2. MVVM Bind Command on Ribbon Button
    Par redkan dans le forum Windows Presentation Foundation
    Réponses: 1
    Dernier message: 17/11/2010, 16h30
  3. [MVVM] Utilisation des InputBindings
    Par tomlev dans le forum Windows Presentation Foundation
    Réponses: 25
    Dernier message: 07/12/2009, 12h09
  4. [MVVM] Les erreurs de Binding
    Par Robin56 dans le forum Windows Presentation Foundation
    Réponses: 11
    Dernier message: 12/07/2009, 12h16

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