获取组件的父表单

时间:2008-12-16 14:27:52

标签: c# vb.net winforms components

我有一个管理其他视觉控件的非可视组件。

我需要引用组件正在运行的表单,但我不知道如何获取它。

我不确定是否添加了一个指定为控件的父元素的构造函数,因为我希望组件只是被放入设计器中。

另一个想法是将父母的财产作为控制,默认值为“我”

任何建议都会很棒

修改

澄清一下,这是组件,而不是控件,请参阅此处:ComponentModel.Component

10 个答案:

答案 0 :(得分:26)

[重要的是要了解下面的ISite技术仅适用于设计时。因为ContainerControl是公共的并且被赋值,所以VisualStudio将编写在运行时设置它的初始化代码。站点在运行时设置,但您无法从中获取ContainerControl]

Here's an article,描述了如何为非可视组件执行此操作。

基本上,您需要向组件添加属性ContainerControl:

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

并覆盖Site属性:

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

如果这样做,ContainerControl将被初始化为设计者引用包含的表单。链接的文章更详细地解释了它。

查看如何执行操作的一个好方法是查看.NET Framework中的类型的实现,这些类型的行为与Lutz Reflector等工具类似。在这种情况下,System.Windows.Forms.ErrorProvider是一个很好的例子:一个需要知道其包含Form的组件。

答案 1 :(得分:9)

我使用递归调用来走控制链。将其添加到您的控件中。

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
}

编辑:我看到你在输入时修改了你的问题。如果它是一个组件,那个组件的构造函数应该将它的父元素作为参数,父元素应该在构造时传入它。其他几个组件也是如此,例如计时器。

将父控件保存为成员,然后在我上面给出的ParentForm属性中使用它而不是这个。

答案 2 :(得分:3)

您必须设置父容器的方式。你的组件只是一个类,它就像其他所有类一样驻留在内存中。它没有创造它的真实背景,除非有东西告诉你它做了。创建一个父控件属性并进行设置。

或者只是从控件派生并使用FindForm()。并非所有控件都必须具有可见组件

答案 3 :(得分:2)

如果组件正在管理其他可视控件,那么您应该能够通过它们访问父级。

答案 4 :(得分:2)

我发现this solution不需要输入。对于C#我以这种方式实现它:

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
}

这种方式允许用户设置ParentForm,但它由父表单设置为默认值。

我希望它可以帮到你。

答案 5 :(得分:1)

我认为你想使用IComponent的Site属性。它或多或少等同于Parent属性。

答案 6 :(得分:1)

感谢Rob,我在VB.Net程序中使用了您的解决方案,如下所示:

''' <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

在我的博客上引用它: http://www.dailycode.info/Blog/post/2012/07/03/How-to-get-a-user-controls-parent-form-(Windows-forms).aspx

答案 7 :(得分:1)

试试这个......

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

    return parent.FindForm();
}

从组件

中调用GetParentForm(this.Parent)

答案 8 :(得分:-2)

如果与Form相关的组件是有效Form,您可以Form.ActiveForm获取该组件。

答案 9 :(得分:-3)

以上改进是:

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