代码之家  ›  专栏  ›  技术社区  ›  Itay Karo

.NET(非可视)组件

  •  7
  • Itay Karo  · 技术社区  · 14 年前

    我需要创建一个非可视组件, FooComponent ,这将对所有类型的控件进行一些管理 Bar 以它的形式存在。

    我有以下限制:

    1. 这个 食品成分 只能添加到窗体。
    2. 只有一个 食品成分 允许每个表单。
    3. 食品成分 应该注册到窗体关闭事件,并在它激发时注册到所有 酒吧 并发送了 e.Cancel 基于返回值的值。

    #上述1和2应在运行时和设计时执行。 #3事件登记应自动进行,而不是由 食品成分 的用户。

    我在Google和MSDN上搜索了一些帮助并阅读了 Component ComponentDesigner 上课了,但是我没有找到任何可以救人的东西。

    我该怎么办?

    3 回复  |  直到 9 年前
        1
  •  3
  •   JNYRanger    9 年前

    (1) 若要控制组件只能添加到窗体中,请使用 FooComponent 传递窗体的构造函数,但不定义默认构造函数。它被称为:

    FooComponent component = new FooComponent(this);
    

    组件是从窗体本身中创建的。如果不定义默认构造函数,则:

    FooComponent component = new FooComponent();
    

    不会编译。


    (2) 暴露 食品成分 窗体本身的属性,以及 食品成分 ,设置通过表单的 食品成分 this .


    (3) 同样的事情,在 食品成分 ,向传递的表单的结束事件注册


    把它们放在一起,你会得到:

    public class MyForm : Form {
        public FooComponent OwnedComponent { get; set; }
    }
    
    
    public class FooComponent {
    
        public FooComponent (MyForm OwnerForm) {
            OwnerForm.OwnedComponent = this;
            OwnerForm.FormClosing += MyCallback;
        }
    
        private void MyCallback(object sender, FormClosingEventArgs e) {
            ...
        }
    
    }
    



    编辑
    不幸的是,如果您需要默认构造函数,并且它必须是窗体组件上的一个真正的drop,则无法强制要求组件仅在窗体上创建,或者窗体只有该组件的一个实例(无论如何,不是从组件中创建的)。

    问题有两方面:
    (1) 删除组件不会将组件添加到窗体中,而是将其添加到窗体的 components 收藏。因此,即使您可以获得父/所有者的句柄,它也永远不会是表单。

    (2) 正如Neil指出的,将组件放到表单中调用默认构造函数,它不传递任何参数,当然,组件的任何属性(如站点或容器)都不会被填充。


    可能有用:组件可以设计为在以下几种方式创建时得到通知:

    (1) 通过实现一个构造函数 IContainer 参数。当组件被放到窗体上时,生成的代码将调用此构造函数。但是,它将只在运行时执行此操作,而不是在设计时执行。但容器将是表单的句柄 组件 收藏。

    public FooComponent(IContainer container) {...}
    

    (2) 通过实施 ISupportInitialize . 当组件被放到窗体上时,生成的代码将另外调用 BeginInit() EndInit() . 在 EndInit() ,您可以访问 Site Container . 同样,您只能在运行时而不是在设计时得到这个,在这里抛出异常不会阻止组件的创建。

    来自 MSDN Magazine 作者:迈克尔·温哈特和克里斯·塞尔斯。
    April 2003 Building Windows Forms Controls and Components with Rich Design-Time Features
    May 2003 Building Windows Forms Controls and Components with Rich Design-Time Features, Part 2

    这些现在是.chm帮助文件。您需要在文件的属性页中取消阻止,以便在下载后能够读取内容。

        2
  •  1
  •   KeithS    14 年前

    我认为不可能确切地定义包含类可以包含在其中的内容。我当然从来没有见过这样一个实例,在另一个实例中,甚至在WinForms中,我在设置一种类型的属性时遇到错误(甚至是警告)。

    您可以做的事情是为表单定义一个表单派生的祖先,它包含对(内部可见的)FooComponent的引用,在实例化时初始化一个,并附加处理程序。为了获得最好的结果,它应该是无参数的,并且是唯一的构造函数重载,因此它构成了用户提出的任何构造函数的基础。然后,将其设置为一个内部规则,表单从您的祖先类派生而不是直接从表单派生(当代码提交到源代码管理时,您可以使用类似FxCop或类似的代码检查工具来强制执行此操作)。您的用户现在在他们创建的每个表单中都有一个FooComponent,不能创建自己的(它是内部的,应该与您的表单祖先在另一个项目中)并且不必做任何事情,只需从新类派生,就可以使他们的表单按照您想要的方式运行。

        3
  •  1
  •   Community Doug McClean    7 年前

    你要求的太多了。一般来说,让组件知道它们被丢弃的形式是相当困难的。 This answer 可以帮助您实现事件处理程序。您需要实现ISupportInitialize才能获得EndInit()调用来设置事件处理程序。

    防止倍数也是相当困难的,我只能想一个定制设计师,可以提前介入,以防止第二个被添加。