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

C# Discussion :

Interception / Partage d'évènement


Sujet :

C#

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2011
    Messages : 70
    Points : 75
    Points
    75
    Par défaut Interception / Partage d'évènement
    Bonjour,

    Je suis actuellement en train de développer une application dont l'architecture est imposée, et cela me contraint à faire une gestion particulière d'évènement que je ne maîtrise pas.

    Nous réalisons ce projet en WPF, et avons du créer des contrôles utilisateurs, des contrôles propres à notre application. (Ces contrôles sont séparés des fenêtres, ils sont dans un projet séparé).

    Et maintenant, lorsque je clique sur un bouton présent sur un contrôle, un évènement est "levé", et lance un traintement, cependant, il faudrait également qu'il aboutisse à un changement de fenêtre, il me faudrait donc réussir à capter cet évènement dans le second projet, pour pouvoir faire les liaisons au niveau graphique.

    Merci d'avance pour vos idées

  2. #2
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Bonjour.

    J'ai du mal à saisir où est le problème. Normalement le projet contenant les fenêtres est le projet parent et a accès à tous les autres (ce sont des références du projet parent). Autrement dit, si un contrôle déclare un événement, rien n'empêche une des fenêtres d'y souscrire puisqu'elle a connaissance du contrôle.

    Après, on peut bien débattre de la pertinence événements versus commandes mais dans les deux cas on s'appuie sur le fait que le projet parent (les fenêtres) a connaissance des projets enfants (les contrôles). L'alternative est de mettre en place une inversion de dépendance. Ou encore de déclarer une propriété sur les contrôles par laquelle le projet parent spécifiera une de ses commandes, si bien qu'on minimise le couplage.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2011
    Messages : 70
    Points : 75
    Points
    75
    Par défaut
    Merci de ta réponse.

    Quand tu dis souscris, tu pense abonner? Car j'ai vu pas mal de chose sur le sujet, mais j’avouerai que la plupart me sont des notions inconnues.

    En fait, ce que je veux faire, c'est que dès que l'évènement est déclenché dans mon contrôle personnel, il soit également récupéré par la fenêtre hébergeant le contrôle hébergeant le bouton sujet à l'évènement.

    Et je bien qu'on m'ai parlé de délégué, d’expression lambda et autre notions pointus, je reste dans le flou et ne parviens pas à saisir comment "intercepter" cet évènement :s

    Tu as également parlé de commande, cela ne me dis rien dans ce context, je vais voir ce que je peux trouver à ce sujet.


    Edit: J'ai continué mes recherches, et je viens de voir que abonner et souscrire revenait au même, j'ai également vu que c'était bien cela qu'il me falait faire. Cependant, lorsque je regarde les Faq/Tuto, je ne saisis pas la marche à suivre. (que ce soit sur msdn, developpez, ...)
    On parle de s'abonner à un évènement, mais en fait, on abonne quoi? Une méthode?

  4. #4
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Oui, souscrire signifie s'abonner (en français, "souscrire à un abonnement" = "s'abonner"). Apparemment tu es un débutant, je vais donc tâcher de ne pas être brusque et rester concret. On va donc utiliser un exemple : disons que ton contrôle soit un DateTimePicker (ces machins qui permettent à l'utilisateur de sélectionner une date) qui au départ n'a aucune date sélectionné. Tu souhaites ouvrir une fenêtre avec une liste de résultats dès que l'utilisateur aura choisi une date.

    La solution par abonnement ressemble à quelque chose comme ça : un contrôle expose un événement et notre fenêtre s'y abonne directement.
    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
    // L'argument du délégué de l'événement
    public sealed class DateChangedEventArg : EventArg
    {
        public DateTime Date { get; set; }
    }
     
    // Le type de délégué de l'événement
    public delegate void DateChangedEventHandler(Object sender, DateChangedEventArg e);
     
    // Un contrôle avec un événement DateChanged
    public class DateTimePicker : UserControl
    {
        // Il vaudrait mieux implémenter ce champ comme une DependencyProperty 
        // (via DependencyObject.AddHandler/RemoveHandler) mais je simplifie.
        public event DateChangedEventHandler DateChanged;
     
        // Cette méthode sera appelée par le contrôle lui-même en cas de changement de date, pour notifier les abonnés à DateChanged
        private void OnDateChange(DateTime date)
        {
            if (DateChanged != null) DateChanged(this, new DateChangedEventArg { Date = date });
        }
    }
     
    public class MyWindow : Window
    {
        // Côté XAML on déclare un DateTimePicker avec x:Name="Picker"
     
        // A l'initialisation de la fenêtre on s'abonne. Note: de mémoire je ne suis pas sûr que OnLoaded existe ou soit la bonne méthode
        protected override void OnLoaded(...) 
        {
             Picker.DateChanged += OnDateChanged;
        }
     
        // La méthode appelée en réaction au changement de date : même signature que DateChangedEventHandler 
        private void OnDateChanged(object sender, DateChangedEventArg e)
        {
             AfficherFenêtreListeRésultats(e.Date);
        }
    }

    Maintenant la solution par commande routée, assez similaire : un enfant lève une commande et celui-ci remonte la chaîne de ses ancêtres, de son père jusqu'à la fenêtre. Chaque ancêtre a ainsi l'opportunité de réagir. Il existe aussi des commandes non-routées (un objet implémentant ICommand) mais ce n'est pas très intéressant ici.
    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
    // Un contrôle avec un événement DateChanged
    public class DateTimePicker : UserControl
    {
        // Il vaudrait mieux implémenter ces propriétés comme des DependencyProperty 
        // (via DependencyObject.SetValue/GetValue) mais je simplifie.
        public RoutedCommand DateChangedCommand { get; set; }
     
        // Cette méthode sera appelée par le contrôle lui-même en cas de changement de date, pour notifier les abonnés à DateChanged
        private void OnDateChange(DateTime date)
        {
            if (DateChangedCommand != null && DateChangedCommand.CanExecute(date, this))
              DateChangedCommand.Execute(date, this);
        }
    }
     
    // Cette classe regroupe toutes les commandes de l'application.
    public class MyApplicationCommands
    {
        public static readonly RoutedCommand ChangeSearchDate = new RoutedCommand("ChangeSearchDate ", typeof(MyApplicationCommands));
    }
     
    public class MyWindow : Window
    {
        // Côté XAML on déclare un DateTimePicker et on assigne à sa propriété Command
        // la valeur MyApplicationCommands.ChangeSearchDate 
     
        // A l'initialisation de la fenêtre on ajoute un binding à la commande qui nous intéresse, c'est comme l'abonnement.
        protected override void OnLoaded(...) 
        {
             CommandBindings.Add(new CommandBinding(MyApplicationCommands.ChangeSearchDate, OnDateChanged));
             Picker.DateChanged += OnDateChanged;
        }
     
        // La méthode appelée en réaction au changement de date : même signature que DateChangedEventHandler 
        private void OnDateChanged(object sender, ExecutedRoutedEventArgs e)
        {
             AfficherFenêtreListeRésultats((DateTime)e.Parameter);
        }
    }

    A priori les deux solutions ont l'air à peu près identiques si ce n'est que la seconde est un peu plus obscure, bancale et lourdingue. Mais la seconde a un avantage important : avec l'événement, l'abonné doit avoir connaissance de la source. Donc soit c'est un de ses membres, soit ce membre est rendu public ou exposé d'une autre façon. Qui plus est, si l'on change le contrôle, on change l'événement. Plus généralement, si on remanie l'UI, tout sera sans doute à remanier. Autrement dit, le couplage est plus fort, ce qui est mauvais pour faire évoluer le code plus tard.

    En revanche, avec la commande, l'abonné pourrait être autre chose que MyWindow. Et cet abonné n'aurait besoin que de connaître MyApplicationCommands, pas le contrôle qui a activé la commande (notre DateTimePicker). En somme MyWindow est celui qui associe le DateTimePicker à la commande ChangeSearchDate, pas forcément celui qui prend en charge son activation : n'importe quel ancêtre peut le faire. Tel que j'ai conçu cet exemple ça n'a aucun intérêt. Mais imagine que ton DateTimePicker soit maintenant l'enfant d'un autre contrôle, SearchFilter, et que tu souhaites faire gérer l'affichage de la nouvelle fenêtre par ta fenêtre courante : avec un abonnement il faudrait que SearchFilter expose publiquement son DateTimePicker. Avec la commande c'est inutile il suffit de déclarer le binding au niveau de la fenêtre elle-même

    A toi de voir. Pour ma part je ne recommande pas la commande routée dans ce cas-ci, il y a d'autres façons plus propres de découpler. Mais puisque j'en avais parlé et que tu semblais curieux...

    PS : Les commandes routées regardent d'abord les ancêtres du contrôle activateur (notre DateTimePicker) à la recherche d'un binding. Mais si rien n'a été trouvé ce sont ensuite le contrôle avec le focus courant et ses ancêtres qui sont parcourus. Pas très intéressant dans ton cas mais pratique pour couper/copier/coller (pour utiliser ctrl+c dans une textbox). C'est avant tout à cela que sont destinées les commandes.

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2011
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Distribution

    Informations forums :
    Inscription : Septembre 2011
    Messages : 70
    Points : 75
    Points
    75
    Par défaut
    Merci beaucoup de m'apporter tant d'informations

    J'étais en train d'écrire un roman pour répondre, et en fait, je vais passer un peu plus de temps à essayer de saisir le code dans son ensemble.
    Il y a pas mal de chose qui me paraissent flou, et j'abuserai plutôt du temps de Google que du tiens :p

    Cela mis à part, tu as créé un évènement de toute pièces ou bien tu t'es basé sur un évènement existant dans ce code? J'ai un doute

    Et encore merci de ton aide :p

  6. #6
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Pour te répondre, j'ai créé un événement de toutes pièces. Cela dit MS préconise de faire en sorte que les handlers aient une signature type "void handler(object, TArgs)" ou TArgs hérite de EventArgs. D'où sans doute ce sentiment de déjà-vu.

    Enfin, j'apprécie ta volonté de consulter d'abord Google. Cela dit, si quelque chose t'échappait encore, n'hésite pas à demander.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 08/10/2013, 23h40
  2. Interception de l'évènement autofill
    Par judefei dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 14/06/2012, 11h14
  3. [ASP.NET] Interception d'un événement "onclick"
    Par Skyou dans le forum ASP.NET
    Réponses: 2
    Dernier message: 05/05/2010, 18h19
  4. Interception d'un événement
    Par jproto dans le forum AWT/Swing
    Réponses: 14
    Dernier message: 03/10/2006, 15h47
  5. [C#2.0]Interception de l'évènement Ctrl + A
    Par fagos dans le forum Windows Forms
    Réponses: 2
    Dernier message: 19/06/2006, 15h28

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