27 Stimmen

Elternformular der Komponente abrufen

Ich habe eine nicht-visuelle Komponente, die andere visuelle Steuerelemente verwaltet.

Ich benötige einen Verweis auf das Formular, auf dem die Komponente ausgeführt wird, aber ich weiß nicht, wie ich es bekommen kann.

Ich bin unsicher, einen Konstruktor mit der übergeordneten als Kontrolle angegeben hinzufügen, wie ich die Komponente zu arbeiten, indem nur in den Designer fallen gelassen werden soll.

Der andere Gedanke, den ich hatte, war eine Eigenschaft der Eltern als ein Steuerelement, mit dem Standardwert als 'Me' haben

jede Anregung wäre großartig

Bearbeiten:

Zur Klarstellung: Dies ist eine Komponente , nicht ein Kontrolle , siehe hier: ComponentModel.Component

28voto

Joe Punkte 117971

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

Hier ist ein Artikel in dem beschrieben wird, wie man dies für eine nicht-visuelle Komponente tut.

Grundsätzlich müssen Sie eine Eigenschaft ContainerControl zu Ihrer Komponente hinzufügen:

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

und die Eigenschaft Site außer Kraft setzen:

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 das ContainerControl initialisiert, um das enthaltende Formular durch den Designer zu referenzieren. Der verlinkte Artikel erklärt dies im Detail.

Ein guter Weg, um zu sehen, wie man Dinge tut, ist, sich die Implementierung von Typen im .NET Framework anzusehen, die ein ähnliches Verhalten haben, wie das, was Sie mit einem Werkzeug wie Lutz Reflector wollen. In diesem Fall ist System.Windows.Forms.ErrorProvider ein gutes Beispiel: eine Komponente, die ihr enthaltendes Formular kennen muss.

0 Stimmen

Vielen Dank, dies funktionierte gut nach ein paar kleinere Optimierungen (hinzugefügt einige != null Prüfungen zu).

1 Stimmen

Was genau ist ein Dienst? Er ist kein Bestandteil der Komponente.

0 Stimmen

Ich glaube service sollte eigentlich lauten host - Ich habe es umgestellt, und bisher funktioniert es bei mir.

9voto

Rob Prouse Punkte 21205

Ich verwende einen rekursiven Aufruf, um die Kontrollkette zu durchlaufen. Fügen Sie dies zu 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
}

Bearbeiten: Wie ich sehe, haben Sie Ihre Frage geändert, während ich dies tippte. Wenn es sich um eine Komponente handelt, sollte der Konstruktor dieser Komponente die übergeordnete Komponente als Parameter annehmen und die übergeordnete Komponente sollte diesen Parameter bei der Konstruktion übergeben. Mehrere andere Komponenten tun dies, wie z. B. der Timer.

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

16 Stimmen

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

3voto

Brian Rudolph Punkte 5862

Sie müssen den übergeordneten Container auf irgendeine Weise festlegen. Ihre Komponente ist nur eine Klasse, die sich wie alles andere im Speicher befindet. Sie hat keinen wirklichen Zusammenhang mit dem, was sie erstellt hat, es sei denn, etwas sagt Ihnen, dass sie es getan hat. Erstellen Sie eine Parent Control-Eigenschaft und setzen Sie sie.

Oder leiten Sie einfach vom Steuerelement ab und verwenden Sie FindForm(). Nicht alle Steuerelemente müssen eine sichtbare Komponente haben

2voto

BFree Punkte 100035

Wenn die Komponente andere visuelle Steuerelemente verwaltet, sollten Sie in der Lage sein, das übergeordnete Steuerelement über diese zu erreichen.

0 Stimmen

Daran hatte ich auch schon gedacht. Es funktioniert zwar, aber es scheint ein wenig "hakelig" zu sein.

0 Stimmen

Ich widerspreche Ihnen nicht, aber wenn diese Komponente immer an die Steuerelemente desselben Formulars gebunden sein wird, haben Sie nichts zu verlieren.

2voto

Vaclav Svara Punkte 49

Ich fand diese Lösung die keine Eingabe benötigt. Für C# habe ich es auf diese Weise implementiert:

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
}

Auf diese Weise kann das ParentForm vom Benutzer eingestellt werden, aber es wird vom ParentForm als Standard eingestellt.

Ich hoffe, es hilft Ihnen.

1 Stimmen

Funktioniert das auch bei Ihnen? Für mich, host ist immer gesetzt auf null .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X