我有一个管理其他视觉控件的非可视组件。
我需要引用组件正在运行的表单,但我不知道如何获取它。
我不确定是否添加了一个指定为控件的父元素的构造函数,因为我希望组件只是被放入设计器中。
另一个想法是将父母的财产作为控制,默认值为“我”
任何建议都会很棒
修改
澄清一下,这是组件,而不是控件,请参阅此处:ComponentModel.Component
答案 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
答案 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();