2009-06-01 6 views
0

J'ai un formulaire qui peut ouvrir un sous-formulaire (avec ShowDialog). Je veux m'assurer que le sous-formulaire est correctement éliminé lorsque le formulaire principal est terminé. J'ai essayé d'ajouter le sous-formulaire au membre components du formulaire principal, mais pour le moment j'ai obtenu un ArgumentNullException.
Je sais que je peux simplement instancier le components moi-même, mais n'est-ce pas un peu dangereux? Un jour, j'ajouterai un composant dans la vue du concepteur, ce qui générera la ligne new Container() dans le fichier designer.cs, et je ne saurai jamais que j'ai deux composants qui tournent autour du tas.
Existe-t-il un moyen plus simple de s'assurer que le sous-formulaire est éliminé?WinForm disposant d'un sous-formulaire lorsque le formulaire est disposé

EDIT - déplacé ma solution à une réponse

Répondre

0

Ma solution actuelle:
J'ai ajouté la propriété des composants à la forme, et je l'utilise pour accéder à la collection

private IContainer Components{ get { return components ?? (components = new Container());}} 
3

Si vous utilisez le formulaire en ShowDialog, on pourrait supposer que après avoir reçu le résultat que vous pouvez disposer la forme là-bas?

using(MyDialog dlg = new MyDialog()) 
{ 
    result = dlg.ShowDialog(); 
} 
+0

La forme secondaire peut être ouvert plus d'une fois, avec différentes données. Je ne veux pas créer une nouvelle instance chaque fois que je l'ouvre. –

+0

Mais pourquoi vous inquiétez-vous de l'éliminer alors? Quelles sont les ressources que vous utilisez à ce sujet qui ne seraient pas éliminées après un appel de dialogue? – Spence

+0

Après ShowDialog, le formulaire n'est pas automatiquement éliminé. De cette façon, je peux accéder à DialogResult (qui est la raison pour ne pas l'éliminer automatiquement), et juste ShowDialog encore et encore (c'est pourquoi je l'utilise). Je veux m'assurer que le sous-formulaire est éliminé lorsque le formulaire principal est disposé. –

0

Comme par MSDN, les formes modales invoquées par ShowDialog() ne sont pas disposés automatiquement et il incombe au développeur de les disposer:

Lorsqu'un formulaire est affiché sous la forme d'une boîte de dialogue modale, en cliquant sur le Bouton Fermer (le bouton avec un X dans le coin supérieur droit du formulaire) provoque le masquage du formulaire et la propriété DialogResult à définir sur DialogResult.Cancel. Contrairement aux formulaires non modaux, la méthode Close n'est pas appelée par le .NET Framework lorsque l'utilisateur clique sur le bouton de fermeture d'une boîte de dialogue ou définit la valeur de la propriété DialogResult. Au lieu de cela, le formulaire est masqué et peut être affiché à nouveau sans créer une nouvelle instance de la boîte de dialogue. Parce qu'un formulaire affiché en tant que boîte de dialogue n'est pas fermé, vous devez appeler la méthode Dispose du formulaire lorsque le formulaire n'est plus nécessaire par votre application.

Le point pertinent ici est "lorsque le formulaire n'est plus nécessaire". Dans votre cas, il semble que vous ayez besoin du formulaire pour les actions suivantes, par conséquent, l'appel ShowDialog() dans une construction ne serait pas utile.

Ma suggestion serait de disposer de la boîte de dialogue dans la méthode Dispose de votre formulaire principal, ou le plus tôt possible:

protected override void Dispose(bool disposing) 
{ 
    if (disposing && (components != null)) 
    { 
    components.Dispose(); 
    } 
    // dlg is a variable of type Form2(the dialog) 
    if (dlg != null) 
    { 
    dlg.Dispose(); 
    dlg = null; 
    } 
    base.Dispose(disposing); 
} 
+0

Je pense que le point est de savoir comment s'entendre avec le concepteur ici. Normalement disposer est dans .Designer.cs un non déclaré comme partiel. –

+0

Oui, j'en suis conscient. Et les variables de niveau classe sont visibles dans Designer.cs. – Cerebrus

1

Vous pouvez généralement pas remplacer les méthodes de dipose d'une forme, parce qu'il est alread défini dans le fichier Form.Designer.cs. Il y a un petit truc pour ajouter votre propre logique de disposition à un formulaire.

Utilisation de la classe suivante:

public class Disposer : Component 
    { 
     private readonly Action<bool> disposeAction;    

     public Disposer(Action<bool> disposeAction) 
     { 
      this.disposeAction = disposeAction; 
     } 

     protected override void Dispose(bool disposing) 
     { 
      base.Dispose(disposing); 
      this.disposeAction(disposing); 
     } 

     public static Disposer Register(ref IContainer container, Action<bool> disposeAction) 
     { 
      Disposer disposer = new Disposer(disposeAction); 
      if (container == null) 
       container = new System.ComponentModel.Container(); 

      container.Add(disposer); 
      return disposer; 
     } 
    } 

Gardez une liste des sous-formulaires et ajoutez la ligne suivante au constructeur de la mainform:

Disposer.Register(ref this.components, this.MyDisposeAction); 

Lorsque votre mainform est disposé, tous vos sous-formulaires seront également être disposé, par exemple:

private void MyDisposeAction(bool disposing) 
{ 
    if (disposing) 
    { 
    foreach (var subForm in this.subForms) 
    { 
     subForm.Dispose(disposing); 
    } 
    } 
} 
+0

Merci pour l'idée, mais je ne vois pas pourquoi je devrais créer une classe wrapper qui contient tous mes sous-formulaires, puis les disposer l'un après l'autre, si dans le processus je l'enregistre dans les composants (et le créer le chemin, si nécessaire) - Je peux tout de suite enregistrer mes sous-formulaires sur les composants. Voilà à quoi ça sert. A propos de la réécriture de la méthode dispose - J'ai lu quelque part sur SO, que si je le recopie du code du concepteur dans mon propre fichier, il ne sera pas régénéré. –