2009-02-09 4 views
5

Je sais que lorsque vous enregistrez un objet dans les événements attachés de la souris, vous avez des fuites de mémoire. C'est pourquoi vous devez utiliser WeakEvent pattern.Comment les contrôles WPF intégrés gèrent-ils leurs gestionnaires d'événements dans un événement attaché?

J'ai un problème avec ce modèle: Si vous voulez l'utiliser, vous ne pouvez pas définir votre gestionnaire dans le code XAML.

Pour moi, cela signifie que chaque code comme ceci fuites:

<SomeControl Mouse.MouseDown="MyHandler" /> 

Sauf si vous supprimez votre gestionnaire explicitement dans le code (et je doute que tout le monde fait ça). Maintenant, il y a quelque chose que je ne comprends pas:

<Button Click="MyHandler" /> 

Ce code utilise une certaine façon quelque part l'événement Mouse.MouseDown pour détecter un clic sur le bouton. Avec quelques recherches avec réflecteur, j'ai trouvé que cet événement utilise MouseDown de la classe UIElement. Et quand je lis le code de UIElement je ne comprends pas: il n'y a pas de WeakEventManager!

Quelqu'un peut-il m'expliquer comment UIElement reçoit des événements de Mouse.MouseDown sans fuite?

Répondre

7

L'utilisation de gestionnaires normaux dans XAML ne nécessite pas de références faibles.

Ce que vous faites est de créer une référence de mémoire entre le contrôle principal et un contrôle enfant contenu dans ce contrôle; le contrôle de l'enfant dans ce cas est le bouton.

Si quelqu'un maintient une référence à une partie de l'arbre visuel pour le contrôle principal, l'arbre entier restera en mémoire car il est lié (références parent/enfant).

Maintenant, si toutes les références à cette arborescence sont supprimées, la référence d'événement entre parent et enfant (le contrôle principal et le bouton) n'est pas significative car ces contrôles étaient déjà liés par des références parent/enfant. Une fois toutes les références externes supprimées, ce contrôle peut être récupéré.

Les gestionnaires d'événements dans XAML créent uniquement des références d'événement internes. Vous devez faire attention lorsque des clients externes s'inscrivent à un événement sur un contrôle, car vous créez une référence externe qui maintiendra le contrôle actif tant que le lien et le client existent (sauf si c'est une référence faible) .

Votre question concerne les événements reliés. Il ne semble pas y avoir de documentation claire indiquant si les événements attachés provoquent des fuites de mémoire. Il me semble que le contrôle UI qui souscrit à l'événement contient des références à l'événement au lieu de l'inverse, mais je suppose que l'objet événement statique doit avoir un moyen de notifier le contrôle qu'il a été déclenché. Il semble y avoir un manque surprenant de commentaires de la part de Microsoft.

+0

Je suis d'accord avec vous, cependant le gestionnaire en XAML à un événement attaché (je ne parle pas des événements des contrôles mais des événements comme Mouse.MouseDown) peut fuir, car il y a toujours une référence dessus. En interne, la classe Button utilise les événements Mouse.MouseDown (UIElement pour être spécifique) .Et je ne sais pas pourquoi cela ne fuit pas. –

+0

Bon point. Les événements attachés sont des références externes. –