2010-04-20 5 views
3

Je n'arrive pas à gérer le scénario dans lequel un événement est levé et espère obtenir de l'aide.Comment éviter d'élever un événement à un formulaire fermé?

Scénario (voir ci-dessous le code de référence):

  1. Form1 ouvre Form2
  2. Form1 est abonnée à un événement sur Form2 (appelons l'événement FormAction)
  3. Form1 est fermé et Form2 reste ouvert
  4. Form2 déclenche l'événement FormAction

En Form1.form2_FormAction, pourquoi this renvoie une référence à Form1 mais button1.Parent retours null? Ne devraient-ils pas tous les deux retourner la même référence?

Si nous devions omettre l'étape 3, les deux this et button1.Parent renvoient la même référence.

Voici le code que je utilise ...

Form1:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click (object sender , EventArgs e) 
    { 
     // Create instance of Form2 and subscribe to the FormAction event 
     var form2 = new Form2(); 
     form2.FormAction += form2_FormAction; 
     form2.Show(); 
    } 

    private void form2_FormAction (object o) 
    { 
     // Always returns reference to Form1 
     var form = this; 

     // If Form1 is open, button1.Parent is equal to form/this 
     // If Form1 is closed, button1.Parent is null 
     var parent = button1.Parent; 
    } 
} 

Form2:

public partial class Form2 : Form 
{ 
    public Form2() 
    { 
     InitializeComponent(); 
    } 

    public delegate void FormActionHandler (object o); 
    public event FormActionHandler FormAction = delegate { }; 

    private void button1_Click (object sender , EventArgs e) 
    { 
     FormAction("Button clicked."); 
    } 
} 

Idéalement, je voudrais éviter de soulever des événements formes fermées/éliminées (dont je ne suis pas sûr est possible) ou trouver un moyen propre de gérer cela dans l'appelant (dans ce cas, Form1).

Toute aide est appréciée.

Répondre

3

Une solution simple serait de montrer votre instance de Form2 en utilisant la commande prioritaire qui prend un propriétaire:

form2.Show(this); 

Cette volonté Assurez-vous que form2 est fermé lorsque Form1 est fermé. C'est généralement une bonne pratique de toute façon dans une application multi-formulaire, de sorte que vous n'avez pas de formulaires sans propriétaire qui circulent.

Mise à jour: le modèle d'événement est juste un moyen de gérer la communication entre les formulaires. Dans votre cas, ce n'est pas vraiment approprié car le formulaire qui reçoit l'événement peut se fermer sans que le formulaire ne soulève l'événement. Une alternative serait d'écrire Form2 avec un constructeur qui inclut une instance de Form1 en tant que paramètre (qui serait enregistré en tant que membre de niveau formulaire comme _Receiver ou quelque chose).Au lieu d'élever un événement, Form2 appellerait une méthode définie dans Form1 après vérification pour voir si _Receiver a été disposé déjà:

if (!_Receiver.IsDisposed) 
{ 
    _Receiver.SomeMethod("some method"); 
} 

Si votre instance de Form1 est toujours là, sa méthode est appelée; s'il a été fermé et éliminé, sa méthode ne sera pas appelée. Puisque Form2 est toujours disponible, vous pouvez également transformer _Receiver en propriété publique et définir son "propriétaire" sur un autre Form1 à tout moment.

+0

La conception de l'application permet aux formulaires enfants de rester ouverts après la fermeture du parent. Malheureusement, je ne suis pas en mesure de changer le design. –

4

Lorsque vous fermez form1 vous devez vous désabonner de l'événement:

form2.FormAction -= form2_FormAction; 
+0

La portée de form2 ne le permet pas. –

+0

@Steve - alors vous devrez étendre la portée de 'form2' pour qu'il le fasse. Sauf si vous vous désinscrivez de l'événement, votre gestionnaire sera appelé. – ChrisF

+0

Pourquoi ne pouvez-vous pas modifier la portée? Voulez-vous être en mesure d'ouvrir plusieurs Form2s? – tanascius

Questions connexes