Winforms:不同用户控件的通用主机窗体?

Winforms:不同用户控件的通用主机窗体?,winforms,user-controls,Winforms,User Controls,我正在处理一个Winforms项目,该项目将有几个“查找”样式的用户控件。这些控件可以嵌入各种形式,但通常是独立的。我想设计一个Windows窗体,它可以承载一个通用的用户控件,并执行这些查找常见的几个任务。我的大脑告诉我这样做,但这显然不起作用: public partial class LookupHostForm<TUserControl> : Form where TUserControl : UserControl public分部类LookupHostForm:Form

我正在处理一个Winforms项目,该项目将有几个“查找”样式的用户控件。这些控件可以嵌入各种形式,但通常是独立的。我想设计一个Windows窗体,它可以承载一个通用的用户控件,并执行这些查找常见的几个任务。我的大脑告诉我这样做,但这显然不起作用:

public partial class LookupHostForm<TUserControl> : Form where TUserControl : UserControl
public分部类LookupHostForm:Form,其中TUserControl:UserControl

是否有一种方法可以使用一个表单托管多个用户控件,而表单不知道/不关心用户控件是什么?

您当然可以根据需要执行操作

只需添加一个构造函数,该构造函数接受您想要的UserControl类型或实例。然后将其作为窗体的子控件添加到构造函数中。或者添加一个虚拟方法,该方法创建感兴趣的特定控件,并且对于所需的每个变体都有一个派生类,其中每个派生类都会覆盖虚拟类并返回正确的类型。或者具有指定控件的属性。有很多方法可以做到这一点。

表单“承载”用户控件的方法是将用户控件的实例作为子控件添加到表单中。每个表单都有一个公开
ControlsCollection
类的public。这是该窗体承载的所有子控件的集合

您只需将用户控件添加到表单的控件集合中。这将完全达到您想要的效果。例如:

CustomUserControl uc = new CustomUserControl();
myForm.Controls.Add(uc);
public class HostForm : Form
{
    public void SetChildControl<TUserControl>(TUserControl ctrl) where TUserControl : UserControl
    {
        // Add the specified user control to the forms controls collection
        this.Controls.Add(ctrl);

        // Dock the user control in its host form
        ctrl.Dock = DockStyle.Fill;
    }
}
为了消除这种效果,您可能还希望停靠用户控件以填充其宿主窗体的整个客户端区域,或者将其锚定到所有四个面。当用户控件的宿主窗体大小更改时,停靠将导致用户控件的大小更改。锚定将只在主机的中间控制用户控件。使用用户控件的适当名称和属性来实现此效果

当然,任何表单对象都可以做到这一点。我将对
表单
类进行子类化,并公开一个强类型方法,以将我的用户控件的实例添加到其控件集合中。例如:

CustomUserControl uc = new CustomUserControl();
myForm.Controls.Add(uc);
public class HostForm : Form
{
    public void SetChildControl<TUserControl>(TUserControl ctrl) where TUserControl : UserControl
    {
        // Add the specified user control to the forms controls collection
        this.Controls.Add(ctrl);

        // Dock the user control in its host form
        ctrl.Dock = DockStyle.Fill;
    }
}
公共类主机窗体:窗体
{
public void SetChildControl(TUserControl ctrl),其中TUserControl:UserControl
{
//将指定的用户控件添加到窗体控件集合
this.Controls.Add(ctrl);
//以宿主形式停靠用户控件
ctrl.Dock=DockStyle.Fill;
}
}

您认为它不起作用是什么意思?设计器可能无法正确解析,但一旦完成了基本设计,我不明白为什么代码在运行时无法工作。它会中断
InitializeComponent()
“…添加一个采用该类型的构造函数…”我该怎么做
public void new(Type userControlType…)
然后使用
Activator.CreateInstance
或类似的东西?谢谢,是的,我知道“如何”了。我要寻找的是
myForm.Controls.Add(new CustomUserControl())
的一种方法,不必知道
CustomUserControl
的类型。@AJ:这是最简单的部分。您可以像第一次尝试的那样使用泛型。但是,不必重载表单的构造函数(您说这会干扰
InitializeComponent
),您只需公开一个内部调用
this.Controls.Add()的公共方法
。好极了,我喜欢这种方法,因为我可以为我的查找控件创建一个基本接口,而且它的加载速度似乎比使用反射更快。谢谢!@AJ:是的,我绝对不会使用反射来实现这种效果。我想可能也有办法通过重载构造函数来实现,但我没有尝试o调查这一点,因为在ctor中有这样的逻辑似乎并不重要。我很高兴这对你有用!