C#WinForms,在UserControl中添加一个UserControl

本文关键字:UserControl 一个 添加 C#WinForms | 更新日期: 2023-09-27 18:00:16

我正在开发一个以GUI为中心的项目,该项目使用自定义的UserControl拖放对象。我在表单上创建和显示UserControl没有问题。我遇到问题的地方是创建不同类型的UserControl并将其与第一个关联。

我有一个名为HardwareComponent的类,它是主窗体的子窗体。当对象构造时,我希望一个名为主窗体的ComponentPanel的对象也构造,但也作为控件添加到主窗体中。这样,当用一个调用创建一个新组件时,面板会自动创建,但它们在表单上仍然是两个独立的控制对象

这里有一个狙击坑:

class HardwareComponent : UserControl
{
    public ComponentPanel panel;
    public HardwareComponent()
    {
        panel = new ComponentPanel();
        panel.Location = new Point(this.Right + 5, this.Top);
        panel.Name = Guid.NewGuid().ToString();
        Parent.Controls.Add(panel);
    }
}

从字面上看,ComponentPanel对象:

class ComponentPanel : UserControl
{
    public string guid { get; set; }
    public ComponentPanel()
    {
    }
}

*未显示OnPaint覆盖方法

如果我将ComponentPanel的创建移到表单类中,这表明没有问题,但现在我必须从表单类中创建这两个对象。我觉得让组件创建面板是一种更干净的方法。

无论如何,当我执行上面的代码时,当试图将"panel"添加到窗体(硬件组件类的父级)时,它会抛出一个NullReferenceException。我试图使面板对象成为一个公共全局变量,认为这是一个"权限"问题。仍然没有骰子。

本质上,我希望这个UserControl创建另一个UserControl,但将其添加到表单中。这是最佳实践吗?或者我必须从表单类中添加两者吗?

编辑:汉斯在这里回答了更深层次的问题。我没有意识到空引用异常实际上指向"Parent"。我以为它不喜欢我的对象。我没有考虑这样一个事实,即由于我在运行时动态创建对象,然后定义其属性,然后将其添加到表单中,Parent没有定义。所以构造函数不知道谁是父级。

我这样做的主要目的是从合乎逻辑的角度出发。这两个物体可以被认为是一体的。该组件在表单上显示为一个块。双击它时,会出现一个面板,显示该块中的内容。两个物体必须同时可见,并且可以自由移动,因此这不仅仅是视图的改变。

我的解决方案是使用一个方法来创建私生子对象,该子对象在创建Component对象后从主窗体调用。示例:

this.Controls.Add(dummyComponent);
dummyComponent.InitializePanel();

C#WinForms,在UserControl中添加一个UserControl

我同意这样做是一个糟糕的设计。然而,实现这一点的一种方法是重写OnParentChanged()并在那里创建"兄弟"控件:

class HardwareComponent : UserControl
{
    public ComponentPanel panel = null;
    public HardwareComponent()
    {
    }
    protected override void OnParentChanged(EventArgs e)
    {
        if (this.panel == null && this.Parent != null)
        {
            this.panel = new ComponentPanel();
            this.panel.Location = new Point(this.Right + 5, this.Top);
            this.panel.Name = Guid.NewGuid().ToString();
            this.Parent.Controls.Add(panel);
        }
        base.OnParentChanged(e);
    }
}