我有一个管理其他可视控件的非可视组件。
我需要引用该组件正在运行的表单,但我不知道如何获取它。
我不确定添加一个将父级指定为控件的构造函数,因为我希望组件只需被放入设计器即可工作。
我的另一个想法是拥有一个父属性作为控件,默认值为“我”
任何建议都会很棒
编辑:
为了澄清,这是一个组件,而不是一个控件,请参见此处:ComponentModel.Component
我有一个管理其他可视控件的非可视组件。
我需要引用该组件正在运行的表单,但我不知道如何获取它。
我不确定添加一个将父级指定为控件的构造函数,因为我希望组件只需被放入设计器即可工作。
我的另一个想法是拥有一个父属性作为控件,默认值为“我”
任何建议都会很棒
编辑:
为了澄清,这是一个组件,而不是一个控件,请参见此处:ComponentModel.Component
[It is important to understand that the ISite technique below only works at design time. Because ContainerControl is public and gets assigned a value VisualStudio will write initialization code that sets it at run-time. Site is set at run-time, but you can't get ContainerControl from it]
Here's an article that describes how to do it for a non-visual component.
Basically you need to add a property ContainerControl to your component:
public ContainerControl ContainerControl
{
get { return _containerControl; }
set { _containerControl = value; }
}
private ContainerControl _containerControl = null;
and override the Site property:
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;
}
}
}
}
If you do this, the ContainerControl will be initialized to reference the containing form by the designer. The linked article explains it in more detail.
A good way to see how to do things is to look at the implementation of Types in the .NET Framework that have behaviour similar to what you want with a tool such as Lutz Reflector. In this case, System.Windows.Forms.ErrorProvider is a good example to look at: a Component that needs to know its containing Form.
我使用递归调用来遍历控制链。将此添加到您的控件中。
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 属性中使用它而不是这个。
You will have to set the parent container some how. Your component is just a class, that resides in memory just like everything else. It has no true context of what created it unless something tells you that it did. Create a Parent control property and set it.
Or simply derive from control and use FindForm(). Not all controls must have a visible component
如果组件正在管理其他可视控件,那么您应该能够通过它们到达父级。
I found this solution which does not need the input. For C# I implemented it this way:
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
}
This way allows the set ParentForm by user, but it is set by parent form as Default.
I hope it helps you.
Try This ....
private Form GetParentForm(Control parent)
{
if (parent is Form)
return parent as Form;
return parent.FindForm();
}
Call GetParentForm(this.Parent)
from component
我认为您想使用 IComponent 的 Site 属性。它或多或少等同于 Parent 属性。
Thanks Rob, I used your solution in a VB.Net program, looks like this:
''' <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
Referenced it on my blog: http://www.dailycode.info/Blog/post/2012/07/03/How-to-get-a-user-controls-parent-form-(Windows-forms).aspx
If the component related Form
is the active Form
you may get it by Form.ActiveForm
.
A improvement of above is:
public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm();