代码之家  ›  专栏  ›  技术社区  ›  Pondidum

获取组件的父窗体

  •  27
  • Pondidum  · 技术社区  · 16 年前

    我有一个非视觉组件,用于管理其他视觉控件。

    我需要一个组件正在运行的表单的参考,但我不知道如何获得它。

    我不确定是否添加一个将父级指定为控件的构造函数,因为我希望组件只需放入设计器中即可工作。

    我的另一个想法是将父级的属性作为控件,默认值为“Me”

    任何建议都很好

    编辑:

    为了澄清,这是 组成部分 ,不是a 控制 ,请参阅此处: ComponentModel.Component

    9 回复  |  直到 16 年前
        1
  •  27
  •   Michael F    12 年前

    [重要的是要理解下面的ISite技术仅在设计时有效。因为ContainerControl是公共的,并且被分配了一个值,VisualStudio将编写初始化代码,在运行时对其进行设置。Site是在运行时设置的,但您无法从中获取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将被初始化为由设计器引用包含表单。链接文章对此进行了更详细的解释。

    了解如何做事的一个好方法是查看中Types的实现。NET Framework,其行为与您使用Lutz Reflector等工具所期望的行为相似。在这种情况下,系统。窗户。形式。ErrorProvider是一个很好的例子:一个需要知道其包含形式的组件。

        2
  •  9
  •   Rob Prouse    16 年前

    我使用递归调用来向上遍历控制链。将此添加到您的控件中。

    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
    }
    

    编辑: 我看到你在我打字的时候修改了你的问题。如果它是一个组件,则该组件的构造函数应将其父级作为参数,并且父级在构造时应传递this。其他几个组件也可以做到这一点,比如定时器。

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

        3
  •  3
  •   Brian Rudolph    16 年前

    您必须以某种方式设置父容器。你的组件只是一个类,它和其他东西一样驻留在内存中。除非有什么东西告诉你它创造了它,否则它没有真正的背景。创建父控件属性并对其进行设置。

    或者简单地从控件派生并使用FindForm()。并非所有控件都必须有可见的组件

        4
  •  2
  •   BFree    16 年前

    如果组件集正在管理其他视觉控件,那么您应该能够通过它们到达父级。

        5
  •  2
  •   Jonathan Wood    12 年前

    我发现了 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,但父窗体将其设置为默认值。

    我希望这对你有帮助。

        6
  •  2
  •   benka Csaba    11 年前

    试试这个。...

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

    呼叫 GetParentForm(this.Parent) 从组件

        7
  •  1
  •   arul    16 年前

    我认为您想使用IComponent的Site属性。它或多或少相当于父属性。

        8
  •  1
  •   Jonathan Wood    12 年前

    上述改进是:

    public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm();
    
        9
  •  -2
  •   Pollitzer    8 年前

    如果组件相关 Form 是否处于活动状态 表格 你可能会得到它 Form.ActiveForm .

        10
  •  -3
  •   GeoB    9 年前