2008-10-16 12 views
5

Comment puis-je lancer un événement qui a accesseurs comme celui-ci:Lancement d'un événement qui a accesseurs

public event EventHandler CanExecuteChanged 
    { 
     add 
     { 
     CommandManager.RequerySuggested += value; 
     } 
     remove 
     { 
     CommandManager.RequerySuggested -= value; 
     } 
    } 

Si elle était un événement normal je lance par:

CanExecuteChanged(sender, EventArgs..). 

Mais ici ne fonctionne pas - je ne peux faire

CanExecuteChanged +=.. 

pour fixer une méthode faire l'événement - mais je ne peux pas le lancer.

Une documentation sur le sujet serait également appréciée. Merci.

EDIT L'événement provient d'une ICommand implémentant une classe dans WPF. il n'y a plus rien à montrer :). Et non - le CommandManager.RequerySuggested (this, EventArgs.Empty); ne fonctionne pas.

EDIT2 Vous ne savez pas quoi dire - l'exemple de Jon aurait dû fonctionner même si la méthode add est appelée correctement - quand j'essaie d'appeler l'événement - c'est null: |. Je vais probablement supprimer des événements avec des accesseurs.

+0

trouvé le problème. Si vous encapsulez un délégué, vous devez appeler le délégué directement au lieu de l'événement, comme vous le faites normalement. Voir le message ci-dessous. – Gishu

Répondre

3

Cet événement est juste abonnée à et d'un autre événement désabonnement.Si vous voulez que vos abonnés (et seulement vos abonnés - et non ceux séparés de l'autre événement) soient appelés, vous devez garder vos abonnés séparément. Par exemple, vous pouvez changer le code à quelque chose comme:

private EventHandler canExecuteChanged; 

public event EventHandler CanExecuteChanged 
{ 
    add 
    { 
     CommandManager.RequerySuggested += value; 
     canExecuteChanged += value; 
    } 
    remove 
    { 
     CommandManager.RequerySuggested -= value; 
     canExecuteChanged -= value; 
    } 
} 
0

Vous devez appeler directement les événements sous-jacents. Dans votre cas, il semble que ce serait:

<blockquote>CommandManager.RequerySuggested(sender, EventArgs.…)</blockquote> 

/EDIT: Ok, je ne l'ai pas remarqué que CommandManager est une classe-cadre. Dans ce cas, vous ne voulez évidemment pas faire ce que j'ai proposé. La solution de Jon est au point: vous devez garder une trace de votre propre événement et l'invoquer (par exemple en tant que délégué). Conformément à l'exemple de Jon, l'invocation ressemblerait à ceci:

canExecuteChanged(sender, EventArgs.Empty); 
4

Je pense que vous avez des événements confondus avec les délégués. Seule la classe exposant l'événement peut l'augmenter ... Les autres ne peuvent s'abonner que pour se désabonner. Si vous appelez l'événement depuis la classe déclarant l'événement, il devrait fonctionner comme un délégué normal.

La meilleure page que j'ai pu trouver sur Events vs Delegates. Lisez ..

Pouvez-vous poster un plus grand .. extrait quelque chose semble mal ..

Tueur Mise à jour

Je pense que je vois enfin votre problème et comment le résoudre. Réponse courte: Il ne connaît pas le nom du délégué à invoquer si vous écrivez vos propres accesseurs. Si ce n'est pas le cas ... le compilateur ajoute le délégué privé du nom connu et peut donc l'appeler

Cet extrait de code montre ce que je veux dire. Ce MSDN article showed me the light. Grande question mec .. J'ai perdu 30 minutes. Upvoted :)

public class Hash1 
    { 

     private EventHandler myHomeMadeDelegate; 
     public event EventHandler FancyEvent 
     { 
      add 
      { 
       //myDelegate += value; 
       myHomeMadeDelegate = (EventHandler)Delegate.Combine(myHomeMadeDelegate, value); 
      } 
      remove 
      { 
       //myDelegate -= value; 
       myHomeMadeDelegate = (EventHandler)Delegate.Remove(myHomeMadeDelegate, value); 
      } 
     } 
     public event EventHandler PlainEvent; 


     public Hash1() 
     { 
      FancyEvent += new EventHandler(On_Hash1_FancyEvent); 
      PlainEvent += new EventHandler(On_Hash1_PlainEvent); 

      // FancyEvent(this, EventArgs.Empty); //won't work:What is the backing delegate called? I don't know 
      myHomeMadeDelegate(this, EventArgs.Empty); // Aha! 
      PlainEvent(this, EventArgs.Empty); 
     } 

     void On_Hash1_PlainEvent(object sender, EventArgs e) 
     { 
      Console.WriteLine("Bang Bang!"); 
     } 

     void On_Hash1_FancyEvent(object sender, EventArgs e) 
     { 
      Console.WriteLine("Bang!"); 
     } 
} 
+0

Damn .. J'ai effectivement trouvé cet article moi-même, mais il n'y avait pas assez d'extraits de code :) alors je me déplace. En outre, Jon a expliqué à peu près la même chose que plus courte :). Mais merci d'y aller plus en détail.Mise à jour: P – sirrocco

1

Ok, je trouve que si je veux déclencher cet événement que vous devez faire:

CommandManager.InvalidateRequerySuggested();. 
0

wow, juste eu des problèmes similaires. La réponse qui m'a aidé à comprendre est un peu comme Gishu's.

également des spécifications C#, http://www.microsoft.com/en-us/download/details.aspx?id=7029, sous la rubrique « 10.8.1 événements comme le terrain », il dit « Lors de la compilation d'un événement comme champ, le compilateur crée automatiquement le stockage de tenir le délégué, »

spécifications dit aussi:

Ainsi, une déclaration d'événement instance de la forme:

class X 
{ 
    public event D Ev; 
} 

pourrait être compilé à quelque chose d'équivalent à:

class X 
{ 
    private D __Ev; // field to hold the delegate 

    public event D Ev { 
     add { 
     lock(this) { __Ev = __Ev + value; } 
     } 

     remove { 
     lock(this) { __Ev = __Ev - value; } 
     } 
    } 
} 

Si vous faites quelque chose comme le code ci-dessous, le compilateur compile avec succès:

namespace ConsoleApplication1 
{  
    class Program 
    { 
     public event EventHandler ss; 

     Program() 
     { 
      if (null != ss) 
      { 
       ss(this, EventArgs.Empty) ; 

      } 
     } 

     static void Main(string[] args) 
     { 
      new Program(); 
     } 
    } 
} 

Et Si vous ajoutez des accesseurs à ss ci-dessus, il ne compilera PAS:

namespace ConsoleApplication1 
{  
    class Program 
    { 
     public event EventHandler ss 
     { 
      add { } 
      remove { } 
     } 

     Program() 
     { 
      if (null != ss) 
      { 
       ss(this, EventArgs.Empty) ; 

      } 
     } 

     static void Main(string[] args) 
     { 
      new Program(); 
     } 
    } 
} 

Il existe deux types d'événements ont montré ici

  1. événements comme champ => nous pouvons invoquer
  2. événements avec accesseurs => on ne peut invoquer (ne peut pas trouver ce dans les specs pourquoi, peut-être Je l'ai manqué) (et ne faisait que tester ceci sur Visual Studio 2005, et les spécifications étaient les dernières, je suppose)