Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET(非可视)组件_C#_.net_Visual Studio_Winforms - Fatal编程技术网

C# .NET(非可视)组件

C# .NET(非可视)组件,c#,.net,visual-studio,winforms,C#,.net,Visual Studio,Winforms,我需要创建一个非可视组件,FooComponent,它将对驻留在其表单中的所有Bar类型的控件进行一些管理 我有以下限制: FooComponent只能添加到表单中 每个表单只允许一个FooComponent FooComponent应该注册到表单关闭事件,当它触发时,注册到所有栏上的某个函数,并根据返回的值发送e.Cancel值 #上述1和#2应在运行时和设计时执行。 #3事件注册应自动进行,而不是由FooComponent的用户进行 我在Google和MSDN上搜索了一些帮助,并阅读了Com

我需要创建一个非可视组件,
FooComponent
,它将对驻留在其表单中的所有
Bar
类型的控件进行一些管理

我有以下限制:

  • FooComponent
    只能添加到表单中
  • 每个表单只允许一个
    FooComponent
  • FooComponent
    应该注册到表单关闭事件,当它触发时,注册到所有
    栏上的某个函数,并根据返回的值发送
    e.Cancel
  • #上述1和#2应在运行时和设计时执行。 #3事件注册应自动进行,而不是由
    FooComponent
    的用户进行

    我在Google和MSDN上搜索了一些帮助,并阅读了
    Component
    ComponentDesigner
    类,但我没有找到任何帮助


    我该怎么办?

    我认为不可能准确地定义包含在其中的类。我当然从未见过在另一种类型(甚至WinForms)中设置一个属性时出现错误(甚至警告)的实例

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

    (1)要控制该组件只能添加到表单,使用传递表单的
    FooComponent
    构造函数,不要定义默认构造函数。这叫做:

    FooComponent component = new FooComponent(this);
    
    组件是从表单本身中创建的。通过不定义默认构造函数,这将:

    FooComponent component = new FooComponent();
    
    不会编译


    (2) 在表单本身上公开
    FooComponent
    属性,并在
    FooComponent
    的构造函数中,将传递的表单的
    FooComponent
    设置为
    this


    (3) 同样,在
    FooComponent
    的构造函数中,为传递的表单注册关闭事件


    把这些放在一起,你会得到:

    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()
    中,您可以访问属性,例如
    站点
    容器
    。同样,您只会在运行时得到这个结果,而不是在设计时,在这里抛出异常不会阻止组件的创建

    Michael Weinhardt和Chris撰写的关于组件和控件的古老但优秀的文章很畅销。



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

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


    防止多次重复也很难,我只能想到一个自定义设计器,它可以足够早地介入,以防止添加第二次重复。

    我需要在设计时支持这一点,你知道如何在设计时实现#3吗?不允许空构造函数的缺点是,你将无法在设计时使用控件。OP说他正在创建一个非可视组件,所以这不应该是一个问题。我的意思是构造器是组件构造器。。。我会在问题中澄清我明白你的意思。。。如果他字面上的意思是一个
    组件
    ,他想在表单上拖放,那么你是对的,他必须有一个默认构造函数。谢谢你的回答,但我确实需要默认构造函数才能将组件拖放到表单上。谢谢你的回答,我将浏览这篇文章。我想你可以看看CodeDomSerializer()。这可能是你最好的选择。