2009-06-01 12 views
0

Ich habe ein Formular, das ein Unterformular (mit ShowDialog) öffnen kann. Ich möchte sicherstellen, dass das Unterformular richtig angeordnet wird, wenn das Hauptformular fertig ist. Ich habe versucht, das Unterformular zum components Mitglied des Hauptformulars hinzuzufügen, aber im Moment habe ich eine ArgumentNullException.
Ich weiß, ich kann die components selbst instanziieren, aber ist das nicht ein bisschen gefährlich? Eines Tages werde ich eine Komponente in der Designer-Ansicht hinzufügen, und das wird die new Container() Zeile in der Datei designer.cs erzeugen, und ich werde nie wissen, dass ich zwei Komponenten instanses um den Haufen laufen lasse.
Gibt es einen einfacheren Weg, um sicherzustellen, dass das Unterformular entsorgt wird?WinForm entsorgt ein Unterformular, wenn das Formular entsorgt wird

EDIT - zogen meine Lösung auf eine Antwort

Antwort

0

Meine aktuelle Problemumgehung:
ich die Komponenten Eigenschaft zu dem Formular hinzugefügt haben, und es bin mit der Kollektion für den Zugriff auf

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

Wenn Sie das Formular in Showdialog verwenden, könnte man davon ausgehen, dass, nachdem Sie das Ergebnis erhalten Sie das Formular dort entsorgen könnten?

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

Die Unter Form mehr als einmal geöffnet werden kann, mit verschiedene Daten. Ich möchte nicht jedes Mal, wenn ich es öffne, eine neue Instanz erstellen. –

+0

Aber warum sind Sie besorgt, es dann zu entsorgen? Welche Ressourcen verwenden Sie darauf, die nach einem Show-Dialog-Aufruf nicht entfernt würden? – Spence

+0

Nach ShowDialog wird das Formular nicht automatisch entsorgt. Auf diese Weise kann ich auf das DialogResult zugreifen (was der Grund dafür ist, es nicht automatisch zu entfernen), und ShowDialog es immer und immer wieder (weshalb ich es benutze). Ich möchte sicherstellen, dass das Unterformular entsorgt wird, wenn das Hauptformular entsorgt wird. –

0

Wie pro MSDN, Formen Modal über ShowDialog() aufgerufen werden nicht automatisch angeordnet ist, und die Last ist, auf den Entwickler, sie zu entsorgen:

Wenn ein Formular als ein modales Dialogfeld angezeigt wird, wird durch Klicken der Schaltfläche "Schließen" (die Schaltfläche mit einem X in der oberen rechten Ecke des Formulars) bewirkt, dass das Formular ausgeblendet und die DialogResult-Eigenschaft auf DialogResult.Cancel festgelegt wird. Im Gegensatz zu nicht modalen Formularen wird die Close-Methode nicht von .NET Framework aufgerufen, wenn der Benutzer auf die Schaltfläche zum Schließen eines Dialogfelds klickt oder den Wert der DialogResult-Eigenschaft festlegt. Stattdessen ist das Formular ausgeblendet und kann erneut angezeigt werden, ohne dass eine neue Instanz des Dialogfelds erstellt wird. Da ein als Dialogfeld angezeigtes Formular nicht geschlossen ist, müssen Sie die Dispose-Methode des Formulars aufrufen, wenn das Formular von Ihrer Anwendung nicht mehr benötigt wird.

Der relevante Punkt hier ist "wenn das Formular nicht mehr benötigt wird". In Ihrem Fall scheinen Sie das Formular für nachfolgende Aktionen zu benötigen, daher würde das Umbrechen des Aufrufs in einem using-Konstrukt den Zweck nicht erfüllen.

Mein Vorschlag wäre der Dialog in der Dispose-Methode Ihrer Hauptform zu entsorgen, oder so früh wie möglich:

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

Ich denke, der Punkt ist, wie man hier mit dem Designer auskommt. Normalerweise ist dispose in .Designer.cs nicht als partiell deklariert. –

+0

Ja, mir ist das bekannt. Und Variablen auf Klassenebene sind in Designer.cs sichtbar. – Cerebrus

1

in der Regel können Sie nicht die dipose Methoden eines Formulars überschreiben, weil es alread definiert ist in der Datei Form.Designer.cs. Es gibt einen kleinen Trick, wie Sie Ihre eigene Dispositionslogik zu einem Formular hinzufügen können.

die folgende Klasse verwenden:

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; 
     } 
    } 

eine Liste von subforms halten und die folgenden Zeile Konstruktor der Hauptform hinzufügen:

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

Wenn Ihre Hauptform angeordnet ist, alle Ihre subforms werden auch angeordnet sein, z:

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

Danke für die Idee, aber ich sehe nicht, warum ich eine Wrapper-Klasse erstellen sollte, die alle meine Unterformen enthält, und sie dann nacheinander entsorgt, wenn ich sie dabei in den Komponenten registriere (und sie zusammen erstelle) übrigens, wenn nötig) - ich kann meine Unterformen einfach sofort auf den Komponenten registrieren. Dafür ist es da. Über schreiben die dispose-Methode - ich habe irgendwo anders auf SO gelesen, dass, wenn ich es aus dem Designer-Code in meine eigene Datei kopieren, wird es nicht neu generiert. –

Verwandte Themen