VB.NET - Passage d'un événement en tant que paramètre
J'ai besoin de passer un événement comme un paramètre à une fonction. Est-il un moyen de faire cela?
La raison est que j'ai une séquence de deux lignes de code qui est jonché partout dans mon programme, où je dynamiquement supprimer le gestionnaire à un événement, puis définissez le gestionnaire de nouveau. Je suis en train de faire ce pour plusieurs événements et les gestionnaires d'événements, j'ai donc décidé d'écrire une fonction qui fait cela.
Comme un exemple, disons que j'ai une zone de liste déroulante dans mon code appelé combobox1, et j'ai la fonction appelée indexChangedHandler. Dans plusieurs endroits de mon code, j'ai les deux lignes suivantes:
RemoveHandler combobox1.SelectedIndexChanged, AddressOf indexChangedHandler
AddHandler combobox1.SelectedIndexChanged, AddressOf indexChangedHandler
Maintenant, je ne veux pas continuer à répéter le dessus de deux lignes de code (ou similaires) tout au cours de mon programme, donc, je suis à la recherche d'un moyen de le faire:
Private Sub setHandler(evt As Event, hndler As eventhandler)
RemoveHandler evt, hndler
AddHandler evt, hndler
End Sub
de sorte que partout où ces deux lignes de code(ou similaire) dans mon programme, je peux juste remplacer par:
setHandler(combobox1.SelectedIndexChanged, AddressOf indexChangedHandler)
Jusqu'à présent, le "evt " Manifestation" de la partie de l'argument de la setHandler fonction est de donner une erreur.
P. S: j'ai posé cette question sur un couple d'autres forums et reçois demandé pourquoi je veux définir le gestionnaire immédiatement après l'avoir retiré. La raison en est que l'ajout dynamique d'un gestionnaire d'événements n-fois provoque le gestionnaire doit être exécutée n fois lorsque l'événement se produit. Pour éviter ce, qui est, pour s'assurer que le gestionnaire n'est exécutée qu'une fois, lorsque l'événement se produit, j'ai d'abord supprimer le gestionnaire à chaque fois que je veux ajouter le gestionnaire de façon dynamique.
Vous demandez peut-être pourquoi le gestionnaire être ajoutées à plusieurs reprises, en premier lieu... La raison est parce que j'ai ajouter le gestionnaire qu'après un événement particulier, dire E1, dans mon formulaire a eu lieu (j'ai ajouter le gestionnaire dans le gestionnaire d'événement E1). Et l'événement E1 peut se produire plusieurs fois dans mon formulaire. Si je ne retirez pas le gestionnaire à chaque fois avant de l'ajouter de nouveau, le gestionnaire est ajouté et donc exécutée plusieurs fois.
Quel que soit le cas, le traitement se produisant au sein de la fonction n'est pas d'une extrême importance pour moi en ce moment, mais plutôt simplement le moyen de faire passer un événement en tant que paramètre.
Il n'y a pas de véritable moyen de le faire par programmation, puisque vous ne pouvez pas passer des références à un événement membres de. Je ne suis pas exactement sûr de ce que setHandler est censé faire... pouvez-vous préciser pourquoi vous avez besoin de supprimer un gestionnaire d'événements, puis ajoutez-le droit de retour?
J'étais en train d'éditer mon post pour expliquer pourquoi j'en aurais besoin pour ce faire, s'est interrompu, est revenu et a terminé le montage et soumis, avant de réaliser que vous avez posé la question déjà. Longue histoire courte, la raison en est maintenant inclus dans le message original 🙂
Je vois. Malheureusement, il n'y a vraiment aucun moyen de faire ce que vous demandez ici...
OriginalL'auteur Tracer | 2010-11-10
Vous devez vous connecter pour publier un commentaire.
Bien sûr, vous pouvez passer à des événements autour de... eh Bien, vous pouvez passer
Action(Of EventHandler)
qui peut faire ce que vous voulez.Si vous avez une classe qui définit un événement de la sorte:
Donné un exemple de
ComboBox
vous pouvez ensuite créer des add & supprimer le gestionnaire d'actions comme:(Maintenant, c'est VB.NET 4.0 code, mais vous pouvez le faire de 3.5 à l'aide de
AddressOf
et un peu plus de déblayage sur.)Donc, si j'ai un gestionnaire
Foo
:Et un
Raise
méthode surComboBox
je peux maintenant le faire:Cet écrit le message "ici avec Foo!" comme prévu.
Je peux également créer cette méthode:
Je peux passer dans le gestionnaire d'événements actions comme suit:
Qui, là encore, écrit le message "ici avec Foo!".
Maintenant, une question qui pourrait être un problème, c'est que vous pouvez accidentellement swap de l'ajouter et supprimer du gestionnaire d'événement délégués dans le code - après tout, ils sont du même type. Donc, il est facile de définir fortement typées délégués pour l'ajouter et supprimer des actions comme:
Le code pour définir le délégué instances ne change pas, sauf pour le délégué types:
Donc maintenant cela vous permet d'être très créatif. Vous pouvez définir une fonction qui va prendre ajouter le gestionnaire délégué, la suppression de gestionnaire délégué et d'un gestionnaire d'événement, qui sera le fil-un gestionnaire d'événements, puis de revenir à vous une
IDisposable
que vous pouvez utiliser plus tard pour supprimer le gestionnaire sans avoir besoin de maintenir une référence pour le gestionnaire d'événements. C'est pratique pour l'utilisation deUsing
consolidés.Voici la signature:
Donc, compte tenu de cette fonction, je peux maintenant le faire:
Et cet écrit le message "ici avec Foo!" seulement deux fois. Le premier et le dernier
Raise
les appels sont en dehors de l'abonnement pour le gestionnaire d'événement.Profitez-en!
Delegates
autour, pas laEvents
lui-même, comme demandé dans la question. Une très bonne réponse tout de même.Enigmativity, merci pour votre réponse détaillée. C'était un peu dur pour moi de comprendre si, depuis que j'ai vu certains d'étranges constructions dans votre post (ma première fois de voir une telle syntaxe, veuillez donc nu avec moi). Mais de ce que j'ai compris, je dois toujours le premier explicitement définir l'objet et l'événement en "ah" et "rh", non? ce que je voudrais savoir c'est, est-il de toute façon de ne pas limiter la définition de "ah" à "combobox1.selectedIndexChanged", de sorte que je peux utiliser la même fonction pour définir le gestionnaire sur un objet différent(cbx2), dire, "cbx2.selectedIndexChanged".
Oui. Il suffit de changer le délégué des définitions de
Public Delegate Sub AddHandlerDelegate(Of T)(ByVal eh as T, comboBox as ComboBox)
et vous pouvez le faire fonctionner pour toutComboBox
. si vous avez à faire d'autres événements que je vous suggère d'appeler le déléguéAddSelectedIndexChangedHandler
etc. Un ajouter et supprimer des délégué pour chaque événement et de contrôle.Les événements sont essentiellement des délégués -
Public Delegate Sub EventHandler(ByVal sender As Object, ByVal e As EventArgs)
. Je suis le remplacement d'un délégué à l'autre. Eh bien en fait, je suis de la création d'un des fermetures au cours de laAddHandler
etRemoveHandler
appels et de passer un délégué pour chaque fermeture. 🙂Arrêter de mettre des noms dans le Code des Balises, que les pauses-commentaire-les notifications. 😉 Et oui, exactement, c'était ma réponse. 😉 Mais vous ne devriez pas mélanger cela, il y a une légère et très subtile différence si vous faites cela ou si vous passez par la
Event
(comme demandé) directement. De toute façon +1.OriginalL'auteur Enigmativity
Vous ne pouvez pas passer événements autour.
Event
n'est pas un type, c'est un mot clé qui définit une paire de méthodes, d'ajouter et de supprimer, utilisé pour changer l'état de l'événement membre de la classe. Ils sont très bien comme les propriétés à cet égard (qui ont des méthodes get et set).Comme les propriétés, les ajouter et supprimer des méthodes pouvez faire ce que vous voulez. Généralement, ces faire rien de plus que de maintenir une instance de délégué, qui lui-même est un
MulticastDelegate
ou en d'autres termes, une liste des délégués qui s'appelle un par un, si l'événement est déclenché.Vous pouvez voir clairement cette structure en C#, où il n'est pas masqué avec
AddHandler
/RemoveHandler
, mais vous modifier directement la liste des associés des gestionnaires:myObject.Event += new Delegate(...);
.Et, encore une fois comme des propriétés, d'être un membre d'une classe qui fait des résumés de deux méthodes différentes, il n'est pas possible de littéralement passer un événement comme un objet.
OriginalL'auteur Bobby
Il y a un certain nombre de différentes significations pour le terme "événement", selon le contexte. Dans le contexte que vous recherchez, un Événement est une paire de méthodes qui aura pour effet d'ajouter ou de supprimer un délégué d'une liste de souscription. Malheureusement, il n'y a pas de classe dans VB.NET pour représenter une méthode sans objet joint. On pourrait sans doute utiliser la réflexion pour aller chercher les méthodes appropriées, puis de transmettre ces méthodes à une routine qui appellerait à la fois, mais dans votre situation particulière qui serait probablement stupide.
La seule situation où je peux voir qu'il pourrait être utile de passer un événement dans le sens que vous décrivez serait pour quelque chose comme un IDisposable objet qui souscrit à des événements de longue durée de vie des objets, et qui a besoin de vous désinscrire de tous ses événements lorsqu'il est disposé. Dans ce cas, il peut être utile d'utiliser la réflexion pour aller chercher le supprimer-délégué de la méthode pour chaque événement, puis de le supprimer-délégué méthodes lorsqu'un objet est supprimé. Malheureusement, je ne connais pas de moyen de représenter les événements de récupérer sauf que les littéraux de chaîne, dont la validité n'a pas pu être vérifié jusqu'à ce moment de l'exécution.
OriginalL'auteur supercat