C# 获取组件';s父窗体
我有一个非可视组件,它管理其他可视控件 我需要一个对组件正在运行的表单的引用,但我不知道如何获取它 我不确定是否要添加一个将父级指定为控件的构造函数,因为我希望该组件只需放入设计器中即可工作 我的另一个想法是使用parent属性作为控件,默认值为“Me” 任何建议都很好 编辑:C# 获取组件';s父窗体,c#,vb.net,winforms,components,C#,Vb.net,Winforms,Components,我有一个非可视组件,它管理其他可视控件 我需要一个对组件正在运行的表单的引用,但我不知道如何获取它 我不确定是否要添加一个将父级指定为控件的构造函数,因为我希望该组件只需放入设计器中即可工作 我的另一个想法是使用parent属性作为控件,默认值为“Me” 任何建议都很好 编辑: 为了澄清,这是一个组件,而不是一个控件,请参见此处:我使用递归调用来遍历控制链。将此添加到您的控件中 public Form ParentForm { get { return GetParentForm( th
为了澄清,这是一个组件,而不是一个控件,请参见此处:我使用递归调用来遍历控制链。将此添加到您的控件中
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属性中使用它,而不是此属性。我认为您希望使用IComponent的Site属性。它或多或少相当于父属性。如果componenet正在管理其他可视控件,那么您应该能够通过它们访问父属性 您必须对父容器进行一些设置。您的组件只是一个类,与其他所有组件一样驻留在内存中。除非有什么东西告诉你它是什么造成的,否则它没有真正的背景。创建父控件属性并进行设置
或者简单地从控件派生并使用FindForm()。并非所有控件都必须具有可见组件。[重要的是要了解下面的ISite技术仅在设计时有效。因为ContainerControl是公共的,并且被分配了一个值,VisualStudio将编写初始化代码,在运行时对其进行设置。站点在运行时设置,但您无法从中获取ContainerControl] 这描述了如何为非可视组件执行此操作 基本上,您需要向组件添加属性ContainerControl:
public ContainerControl ContainerControl
{
get { return _containerControl; }
set { _containerControl = value; }
}
private ContainerControl _containerControl = null;
并覆盖站点属性:
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是一个很好的例子:一个需要知道其包含形式的组件。谢谢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
“”
''返回控件的父System.Windows.form
'''
'''
''第一个父窗体,如果未找到父窗体,则为null
'''
公共共享函数GetParentForm(ByVal parent作为控件)作为窗体
Dim form As form=TryCast(父级,窗体)
如果形式不是什么,那么
报税表
如果结束
如果父母不是什么都不是
'向上走控制层次结构
返回GetParentForm(parent.parent)
如果结束
'控件不在窗体上
一无所获
端函数
在我的博客上引用了它:
我找到了不需要输入的。对于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,但它由父窗体设置为默认值
我希望它能帮助你。试试这个
private Form GetParentForm(Control parent)
{
if (parent is Form)
return parent as Form;
return parent.FindForm();
}
从组件调用
GetParentForm(this.Parent)
以上的改进是:
public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm();
如果与
表单
相关的组件是活动的表单
您可以通过表单获得它。活动表单
您是否有可能更具体一点?我在调试时查看了站点属性,似乎没有任何引用父窗体的内容。我已经想到了这一点,虽然它工作,但它确实有点“黑客”我不同意你的看法,但是如果该组件始终与它所在的同一窗体的控件绑定,那么你就不会有任何损失。谢谢,经过一些小的调整(添加了一些!=null检查),它工作得很好。服务到底是什么,它不是组件的任何成员。我认为服务
实际上应该是主机
-我切换了它,到目前为止它对我有效。这在运行时是如何工作的。据我所知,是设计师提供了IDesignerHost实现,因此它只能在设计模式下工作。我很抱歉。将组件拖放到from之后,代码工作正常,设计器将生成初始化代码到ContainerControl属性!因此,要使用该解决方案,您应该将组件redrop到from。您还可以使用Control.FindForm()来实现这一点。这是否真的适用于您?对我来说,host
总是设置为null
。