2010-05-21 3 views
1

J'ai une fenêtre WPF qui ouvre une fenêtre enfant modale pour charger des données. Les deux fenêtres ont un propre viewmodel, maintenant j'ai ce problème: après avoir fermé la fenêtre enfant, il semble toujours fonctionner en arrière-plan!Fenêtre parent-enfant WPF: problème de référence de liaison

Pour fermer la fenêtre enfant, j'ai défini DialogResult à partir de la commande viewmodel; maintenant, si je crée une nouvelle donnée et que je l'édite à partir de la fenêtre parent (avec la fenêtre enfant fermée avant), la fenêtre enfant capture toujours l'événement changé de propriété pour les propriétés précédemment liées.

Comment peut-on éviter cela?

Je voudrais effacer chaque référence avec des données lorsque je ferme la fenêtre modale. Quelle est la meilleure pratique pour le faire?

Répondre

3

Assurez-vous de ne conserver aucune référence à votre fenêtre, même indirecte. L'une des causes les plus fréquentes de fuites sont les événements. Si une fenêtre B ajoute un gestionnaire d'événement à un événement de la fenêtre A, B ne sera pas libéré avant que A ne le soit également. Par exemple, si vous écoutez directement les changements de propriétés, vous devez utiliser le Weak Event Pattern et remplacer tous vos + = par un appel à PropertyChangedEventManager .AddListener. En général, tous les gestionnaires forts que vous ajoutez à un événement doivent être supprimés pour éviter les fuites.

Plus d'informations sur les fuites dans .NET dans this MSDN article.

Vous pouvez utiliser un profileur de mémoire comme le profileur de Scitech ou Jetbrains dotTrace pour voir quels objets gardent vos fenêtres en mémoire.


Edit: En réponse à vos commentaires, votre cas est vraiment plus simple que ce que je pensais d'abord: le Garbage Collector n'a tout simplement pas recueillir encore la fenêtre. Ajout GC.Collect sur Test_Click à des fins de test résout le problème.

Ici, supprimez l'événement SelectionChanged du ComboBox lorsque le formulaire se ferme afin que vous puissiez laisser le GC faire son travail et récupérer le formulaire ultérieurement sans problème. Si vous avez vraiment besoin du formulaire entier pour être publié immédiatement, vous pouvez envisager d'appeler le GC.Collect même si vous devez l'éviter lorsque vous le pouvez.

Éditer 2: En réponse à votre troisième commentaire, cela ne devrait concerner que les objets qui sont partagés entre les vues, et où les changements dans la vue vont changer quelque chose dans un objet partagé. Dans votre projet de test, le SelectionChanged ne fait rien sur la liste d'origine, donc peu importe si l'événement est déclenché ou non. Le formulaire sera collecté éventuellement.

+0

Je vérifie ... mon entité implémente l'interface INotifyPropertyChanged, une propriété de l'entité est liée à SelectedValue de ComboBox dans win enfant; ComboBox, sur le code de la fenêtre enfant derrière, a un gestionnaire d'événements pour SelectionChanged. Ensuite, après avoir fermé la fenêtre enfant, si je change la même propriété d'entité sur la fenêtre parent, le gestionnaire d'événements selectionchanged de ComboBox dans la fenêtre enfant est en train de se déclencher. –

+0

J'ai créé un projet stupide qui montre le comportement. Vous pouvez le télécharger à partir de l'url: http://www.olisoft-olisistemi.it/uploads/WpfApplication2.zip 1) Cliquez sur le bouton "ChildWindow" 2) Fermez le ChildWindow 3) Cliquez sur le bouton "Test" -> l'événement SelectionChanged de ComboBox dans Fire de ChildWindow! Qu'est-ce qui ne va pas?Modèle d'événement faible est la solution? –

+0

Merci, mais si ma fenêtre a plus d'événements sur le code, dois-je toujours supprimer tous les événements de clôture? Ou existe-t-il une meilleure approche? –