创建一个设计者感知的UserControl集合以用于运行时

时间:2010-09-15 16:14:00

标签: c# .net collections user-controls designer

我有一个Panel,我希望在运行时填充一些UserControl。这些控件很复杂,可能是相互依赖的,所以我喜欢它们:

  • 可以使用Visual Studio设计器进行编辑;
  • 处于相同的上下文中(=在同一个类中定义);

这两项要求都是必须的。

考虑到UserControl本身就是一个Control(s)的索引集合,我开始在同一个类中设计我的控件,而不关心它们的真实定位(将指定运行时)。我已经使用与DevComponents带状容器相同的相同方法(非常满意),所以我最初认为使用标准UserControl可以实现相同的目的。

我最终意识到Control一次只能在一个Control.ControlCollection实例中,所以我无法使用Controls属性并将控件添加到另一个面板而不从原始的“虚拟”UserControl中删除它们。

我的问题是:是否有一种干净且受支持的方式来创建这个设计师感知的UserControl集合?我会称这种方法为一种模式,因为它确实增加了代码的清晰度和效率。

谢谢, 弗朗西斯

P.S。:作为一种解决方法,我创建了一个DummyControlContainer类,它继承UserControl并保持在ControlAdded事件中填充的Dictionary映射(代码如下)。想知道是否有更清洁的东西。

public partial class DummyControlContainer : UserControl
{
    private Dictionary<string, Control> _ControlMap;

    public DummyControlContainer()
    {
        InitializeComponent();

        _ControlMap = new Dictionary<string, Control>();
        this.ControlAdded += new ControlEventHandler(DummyControlCollection_ControlAdded);
    }

    void DummyControlCollection_ControlAdded(object sender, ControlEventArgs args)
    {
        _ControlMap.Add(args.Control.Name, args.Control);
    }

    public Control this[string name]
    {
        get { return _ControlMap[name]; }
    }
}

1 个答案:

答案 0 :(得分:0)

在现实世界的项目中测试并使用它后,我越来越相信如果你需要这样的模式,我的解决方案是干净和安全的。该容器旨在填充诸如面板或类似物的控件。为了防止使用可绑定数据源的某些不良行为,我将每个新控件添加到此容器中,并使用自己的BindingContext。享受。

public partial class DummyControlContainer : UserControl
{
    private Dictionary<string, Control> _ControlMap;

    public DummyControlContainer()
    {
        InitializeComponent();

        _ControlMap = new Dictionary<string, Control>();
        this.ControlAdded +=
            new ControlEventHandler(DummyControlCollection_ControlAdded);
    }

    void DummyControlCollection_ControlAdded(object sender,
        ControlEventArgs args)
    {
        // If the added Control doesn't provide its own BindingContext,
        // set a new one
        if (args.Control.BindingContext == this.BindingContext)
            args.Control.BindingContext = new BindingContext();
        _ControlMap.Add(args.Control.Name, args.Control);
    }

    public Control this[string name]
    {
        get { return _ControlMap[name]; }
    }
}