C# 获取组件的父窗体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/371464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get Component's Parent Form
提问by Pondidum
I have a non-visual component which manages other visual controls.
我有一个管理其他视觉控件的非视觉组件。
I need to have a reference to the form that the component is operating on, but i don't know how to get it.
我需要引用该组件正在运行的表单,但我不知道如何获取它。
I am unsure of adding a constructor with the parent specified as control, as i want the component to work by just being dropped into the designer.
我不确定是否添加一个将父级指定为控件的构造函数,因为我希望该组件只需放入设计器即可工作。
The other thought i had was to have a Property of parent as a control, with the default value as 'Me'
我的另一个想法是将父属性作为控件,默认值为“我”
any suggestions would be great
任何建议都会很棒
Edit:
编辑:
To clarify, this is a component, not a control, see here :ComponentModel.Component
为了澄清,这是一个组件,而不是一个控件,请参见此处:ComponentModel.Component
采纳答案by Joe
[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]
[重要的是要了解下面的 ISite 技术仅在设计时有效。因为 ContainerControl 是公共的并被分配了一个值,所以 VisualStudio 将编写初始化代码,在运行时设置它。站点是在运行时设置的,但您无法从中获取 ContainerControl]
Here's an articlethat describes how to do it for a non-visual component.
Basically you need to add a property ContainerControl to your component:
基本上,您需要向组件添加一个属性 ContainerControl:
public ContainerControl ContainerControl
{
get { return _containerControl; }
set { _containerControl = value; }
}
private ContainerControl _containerControl = null;
and override the Site property:
并覆盖 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;
}
}
}
}
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.
如果您这样做,ContainerControl 将被初始化以引用设计者的包含表单。链接的文章更详细地解释了它。
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.
了解如何操作的一个好方法是查看 .NET Framework 中类型的实现,这些实现的行为类似于您使用 Lutz Reflector 等工具所期望的行为。在这种情况下,System.Windows.Forms.ErrorProvider 是一个很好的示例:一个需要知道其包含 Form 的组件。
回答by Rob Prouse
I use a recursive call to walk up the control chain. Add this to your control.
我使用递归调用沿着控制链向上走。将此添加到您的控件中。
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
}
Edit:I see you modified your question as I was typing this. If it is a component, the constructor of that component should take it's parent as a parameter and the parent should pass in this when constructed. Several other components do this such as the timer.
编辑:我看到您在输入此内容时修改了您的问题。如果是组件,则该组件的构造函数应将其父组件作为参数,父组件在构造时应传入 this。其他几个组件会执行此操作,例如计时器。
Save the parent control as a member and then use it in the ParentForm property I gave you above instead of this.
将父控件另存为成员,然后在我上面提供的 ParentForm 属性中使用它,而不是这个。
回答by arul
I think you want to use the Site property of the IComponent. It's more or less an equivalent to the Parent property.
我认为您想使用 IComponent 的 Site 属性。它或多或少相当于 Parent 属性。
回答by BFree
If the componenet is managing other visual controls, then you should be able to get to the parent through them.
如果组件正在管理其他视觉控件,那么您应该能够通过它们到达父级。
回答by Brian Rudolph
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
或者简单地从控件派生并使用 FindForm()。并非所有控件都必须具有可见组件
回答by Mark
Thanks Rob, I used your solution in a VB.Net program, looks like this:
谢谢 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
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
在我的博客上引用了它:http: //www.dailycode.info/Blog/post/2012/07/03/How-to-get-a-user-controls-parent-form-(Windows-forms) .aspx
回答by Vaclav Svara
I found this solutionwhich does not need the input. For C# I implemented it this way:
我找到了不需要输入的解决方案。对于 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
}
This way allows the set ParentForm by user, but it is set by parent form as Default.
这种方式允许用户设置 ParentForm,但它由父表单设置为 Default。
I hope it helps you.
我希望它能帮助你。
回答by sandipmatsagar
Try This ....
尝试这个 ....
private Form GetParentForm(Control parent)
{
if (parent is Form)
return parent as Form;
return parent.FindForm();
}
Call GetParentForm(this.Parent)
from component
GetParentForm(this.Parent)
从组件调用
回答by GeoB
A improvement of above is:
以上的改进是:
public static Form ParentForm(this Control ctrl) => ctrl as Form ?? ctrl.FindForm();
回答by Pollitzer
If the component related Form
is the active Form
you may get it by Form.ActiveForm
.
如果相关的组件Form
是活动的,Form
您可以通过 获得它Form.ActiveForm
。