如何从组件获取父窗体引用






2.82/5 (6投票s)
组件没有像控件那样的 .Parent
属性。 获取对组件所在父窗体实例的引用非常困难。
引言
我一直在开发一个自定义组件,该组件继承并扩展了 BindingSource
组件(正在撰写更详细的文章)。 我需要获取对组件所在父窗体实例的引用。 这被证明非常困难。
背景
组件没有像控件那样的 .Parent
属性。 它们确实有一个 container 属性,但它也没有 parent 属性。 有时将 container 强制转换为 ContainerControl
会起作用(它确实有一个 parent 属性),但在这种情况下它不会正确转换。
所有 Windows Designer 窗体都会添加一个名为“components”的 container,并且所有组件都会添加到此 container 中,并在设计模式下显示在屏幕底部。 从组件内部,很容易获得对 container 的引用,但我无法获得对 container 的父窗体的引用?
我从 MSDN 的 Windows Form Forum 上的 "nobugz" (Hans Passant – Microsoft MVP) 处获得了一些有用的帮助,他发现 Error Provider 组件设法获得了对父窗体的引用,并在名为 "ContainerControl
" 的属性中公开了它。 Error Provider 使用的秘密是重写组件的 Site 函数并捕获 IDesignerHost
服务。
代码
事实证明,解决方案甚至更简单。 所需要做的就是引用基本组件的 Site 属性,并从中获取设计器主机信息。 这是实现目标的一些步骤
- 在您的 Windows 项目中创建一个新项目,并使用“Component”模板。
- 切换到“Code View”并添加以下代码
Imports System.ComponentModel.Design … Private _form As Form Private Sub GetFormInstance() ' called from constructor Dim _host As IDesignerHost = Nothing If MyBase.Site IsNot Nothing Then _host = _ CType(MyBase.Site.GetService(GetType(IDesignerHost)), IDesignerHost) If _host IsNot Nothing Then _form = CType(_host.RootComponent, Form) End Sub
- 打开 Designer 代码(您可能需要切换 Solution Explorer 顶部的“Show All Files”按钮,然后展开组件下的文件以查看带有
.Designer
扩展名的文件)。 - 在默认构造函数的末尾,添加对
GetFormInstance
函数的调用。 代码应如下所示<System.Diagnostics.DebuggerNonUserCode()> _ Public Sub New() MyBase.New() 'This call is required by the Component Designer. InitializeComponent() 'Added by developer GetFormInstance() End Sub
- 现在切换回组件的用户部分类,并添加任何需要操作父窗体的代码。
- 在您的 Windows 应用程序中创建一个 Form,并添加自定义组件(构建后它应在工具箱的顶部列出)。
就是这样。 一旦你理解了 ISite 服务接口中发生的魔法,它允许应用程序与设计器(在这种情况下是 Visual Studio)交互,它就非常简单了。
历史
- 2007 年 10 月 19 日:最初的帖子