2008-12-16 4 views
23

Ich habe eine nicht visuelle Komponente, die andere visuelle Steuerelemente verwaltet.Übergeordnetes Formular für Komponente erhalten

Ich brauche einen Verweis auf das Formular, auf dem die Komponente ausgeführt wird, aber ich weiß nicht, wie Sie es erhalten.

Ich bin nicht sicher, einen Konstruktor mit dem Eltern als Steuerelement angegeben, da ich will, dass die Komponente nur in den Designer gelöscht wird.

An:

Der andere Gedanke ich hatte, war ein Eigentum von Eltern als Kontrolle zu haben, mit dem Standardwert als ‚Me‘

würden irgendwelche Vorschläge

bearbeitet groß sein klärt, ist dies eine Komponente, keine Steuer, siehe hier: ComponentModel.Component

Antwort

23

[Es ist wichtig zu verstehen, dass die unten beschriebene ISite-Technik nur zur Entwurfszeit funktioniert. Da ContainerControl öffentlich ist und einen Wert zugewiesen bekommt, schreibt VisualStudio Initialisierungscode, der es zur Laufzeit festlegt. Site wird zur Laufzeit festgelegt, aber ContainerControl kann nicht von ihr abgerufen werden]

Here's an article beschreibt, wie dies für eine nicht visuelle Komponente zu tun ist.

Grundsätzlich müssen Sie eine Eigenschaft Container Ihrer Komponente hinzuzufügen:

public ContainerControl ContainerControl 
{ 
    get { return _containerControl; } 
    set { _containerControl = value; } 
} 
private ContainerControl _containerControl = null; 

und die Site-Eigenschaft überschreiben:

public override ISite Site 
{ 
    get { return base.Site; } 
    set 
    { 
    base.Site = value; 
    if (value == null) 
    { 
     return; 
    } 

    IDesignerHost host = value.GetService(
     typeof(IDesignerHost)) as IDesignerHost; 
    if (host != null) 
    { 
     IComponent componentHost = host.RootComponent; 
     if (componentHost is ContainerControl) 
     { 
      ContainerControl = componentHost as ContainerControl; 
     } 
    } 
    } 
} 

Wenn Sie dies tun, wird die Container das enthält referenzieren initialisiert werden Formular vom Designer.Der verlinkte Artikel erklärt es genauer.

Eine gute Möglichkeit zu sehen, wie man etwas tut, ist die Implementierung von Typen im .NET Framework, die ein ähnliches Verhalten wie Lutz Reflector haben. In diesem Fall ist System.Windows.Forms.ErrorProvider ein gutes Beispiel: Eine Komponente muss wissen, welche Form sie enthält.

+0

Danke, das funktionierte nach ein paar kleineren Verbesserungen (fügte einige! = Null-Checks dazu hinzu). – Pondidum

+1

Was genau ist Service, es ist kein Mitglied der Komponente. – Peymankh

+0

Ich denke, 'service' soll eigentlich' host' sein - ich habe es umgeschaltet, und es funktioniert für mich bisher. – dlras2

8

Ich benutze einen rekursiven Aufruf, um die Kontrollkette zu durchlaufen. Fügen Sie dies Ihrem Steuerelement hinzu.

public Form ParentForm 
{ 
    get { return GetParentForm(this.Parent); } 
} 

private Form GetParentForm(Control parent) 
{ 
    Form form = parent as Form; 
    if (form != null) 
    { 
     return form; 
    } 
    if (parent != null) 
    { 
     // Walk up the control hierarchy 
     return GetParentForm(parent.Parent); 
    } 
    return null; // Control is not on a Form 
} 

Edit: Ich sehe Sie Ihre Frage geändert, wie ich diese tippte. Wenn es sich um eine Komponente handelt, sollte der Konstruktor dieser Komponente ihr übergeordnetes Element als Parameter verwenden, und das übergeordnete Element sollte dieses Element übergeben, wenn es erstellt wird. Mehrere andere Komponenten tun dies wie der Timer.

Speichern Sie das übergeordnete Steuerelement als ein Mitglied und verwenden Sie es dann in der ParentForm-Eigenschaft, die ich Ihnen oben anstelle von diesem gab.

+10

Sie können auch Control.FindForm() verwenden, um dies zu erreichen. –

1

Ich denke, Sie möchten die Site-Eigenschaft der IComponent verwenden. Es entspricht mehr oder weniger der Parent-Eigenschaft.

+0

jede Chance, dass Sie bitte etwas konkreter sein könnten? Ich habe die Site-Eigenschaft während des Debuggens betrachtet und es scheint nichts zu geben, das auf das übergeordnete Formular verweist. – Pondidum

2

Wenn die Komponente andere visuelle Steuerelemente verwaltet, sollten Sie in der Lage sein, über sie zu den Eltern zu gelangen.

+0

Ich hatte daran gedacht, während es funktioniert, es scheint ein wenig "hacky" – Pondidum

+0

Ich stimme dir nicht, aber wenn diese Komponente immer an die Steuerelemente der gleichen Form gebunden ist, die es ist, dann haben Sie Nichts zu verlieren. – BFree

2

Sie müssen den übergeordneten Container etwas wie einstellen. Ihre Komponente ist nur eine Klasse, die genau wie alles andere im Speicher residiert. Es hat keinen wahren Zusammenhang dessen, was es geschaffen hat, es sei denn, etwas sagt dir, dass es geschah. Erstellen Sie eine übergeordnete Steuerelementeigenschaft, und legen Sie sie fest.

Oder einfach von der Kontrolle ableiten und FindForm() verwenden. Nicht alle Steuerelemente müssen eine sichtbare Komponente haben

1

Dank Rob, ich verwendet, um Ihre Lösung in einem Programm VB.Net, sieht wie folgt aus:

''' <summary> 
''' Returns the parent System.Windows.form of the control 
''' </summary> 
''' <param name="parent"></param> 
''' <returns>First parent form or null if no parent found</returns> 
''' <remarks></remarks> 
Public Shared Function GetParentForm(ByVal parent As Control) As Form 
    Dim form As Form = TryCast(parent, Form) 
    If form IsNot Nothing Then 
     Return form 
    End If 

    If parent IsNot Nothing Then 
     ' Walk up the control hierarchy 
     Return GetParentForm(parent.Parent) 
    End If 

    ' Control is not on a Form 
    Return Nothing 
End Function 

auf meinem Blog referenzierte es: http://www.dailycode.info/Blog/post/2012/07/03/How-to-get-a-user-controls-parent-form-(Windows-forms).aspx

1

I this solution gefunden, die nicht die Eingabe benötigt . Für C# implementiert ich es so:

public partial class RegistryManager : Component, ISupportInitialize 
{ 

    private Form _parentForm; 
    public Form ParentForm 
    { 
     get { return _parentForm; } 
     set { _parentForm = value; } 
    } 

    // Etc.... 

    #region ISupportInitialize 
    public void BeginInit() { } 
    public void EndInit() 
    { 
     setUpParentForm(); 
    } 
    private void setUpParentForm() 
    { 
     if (_parentForm != null) return; // do nothing if it is set 
     IDesignerHost host; 
     if (Site != null) 
     { 
      host = Site.GetService(typeof(IDesignerHost)) as IDesignerHost; 
      if (host != null) 
      { 
       if (host.RootComponent is Form) 
       { 
        _parentForm = (Form)host.RootComponent; 
       } 
      } 
     } 
    } 
    #endregion 
} 

diese Weise den Satz von Parent Benutzern erlaubt, aber es ist von der Mutterform als Standard gesetzt.

Ich hoffe, es hilft Ihnen. Diese

+0

Funktioniert das wirklich für dich? Für mich ist 'host' immer auf' null' gesetzt. –

0

Versuchen ....

private Form GetParentForm(Control parent) 
{ 
    if (parent is Form) 
     return parent as Form; 

    return parent.FindForm(); 
} 

Anruf GetParentForm(this.Parent) von Komponente

-2

Eine Verbesserung der oben ist:

public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm(); 
0

Wenn die Komponente bezogen ist Form die aktive Form Sie bekommen können es von Form.ActiveForm.