简体   繁体   English

C#WinForms,在UserControl中添加UserControl

[英]C# WinForms, adding a UserControl within a UserControl

I'm working on a project that is very GUI-centric with custom UserControl drag and drop objects. 我正在一个非常以GUI为中心的项目,带有自定义UserControl拖放对象。 I am not having a problem creating and displaying my UserControl on the form. 我在窗体上创建和显示UserControl时没有问题。 Where I am having issues is creating a different type of UserControl and associating it with the first. 我遇到的问题是创建另一种类型的UserControl并将其与第一种关联。

I have a class called HardwareComponent that is a child of the main form. 我有一个名为HardwareComponent的类,它是主要形式的子级。 When the object constructs, I want an object called ComponentPanel to also construct but be added as a control to the main form as well. 在构造对象时,我也希望构造一个名为ComponentPanel的对象,但也应将其作为控件添加到主窗体中。 That way the Panel gets created automatically when creating a new Component with a single call, but they remain two separate control objects on the form. 这样,通过一次调用创建新的组件时,将自动创建面板,但是它们在表单上仍是两个单独的控件对象。

Here's a snippit: 这是一个摘录:

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);
    }
}

And literally the ComponentPanel object: 实际上是ComponentPanel对象:

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

    public ComponentPanel()
    {

    }
}

*not shown are the OnPaint override methods *未显示的是OnPaint覆盖方法

If I move the creation of the ComponentPanel to the form class, it shows no problem but now I have to create both objects from the form class. 如果我将ComponentPanel的创建移动到表单类,则没有问题,但是现在我必须从表单类创建两个对象。 I feel it a cleaner approach to have the Component create the Panel. 我觉得让组件创建面板是一种更干净的方法。

Anyway, when I execute the code above, it throws a NullReferenceException when attempting to add 'panel' to the form (the parent of the Hardware Component class). 无论如何,当我执行上面的代码时,尝试向表单(“硬件组件”类的父级)添加“面板”时,它将引发NullReferenceException。 I attempted to make the panel object a public global variable thinking it was a "permissions" issue. 我试图将面板对象作为一个公共全局变量,认为这是一个“权限”问题。 Still no dice. 仍然没有骰子。

Essentially I want this UserControl to create another UserControl but add it to the form. 本质上,我希望此UserControl创建另一个UserControl,但将其添加到窗体中。 Is this best practice? 这是最佳做法吗? Or do I have to add both from the form class? 还是我必须同时从表单类中添加两者?

EDIT: Hans answered the deeper question here. 编辑:汉斯在这里回答了更深层的问题。 I did not realize the null reference exception was actually pointing to "Parent". 我没有意识到null引用异常实际上是指向“父母”的。 I thought it didn't like my object. 我以为它不喜欢我的对象。 I did not think about the fact that since I create the object dynamically at run time, then define it's properties, then add it to the form, Parent has no definition. 我没有考虑过这样一个事实,因为我是在运行时动态创建对象,然后定义其属性,然后将其添加到表单中,所以Parent没有定义。 So the constructor doesn't know who parent is. 因此,构造函数不知道谁是父母。

My main purpose for doing this is from a logical stand point. 我这样做的主要目的是从逻辑的角度出发。 These two objects can be thought of as one in the same. 这两个对象可以被视为同一对象。 The component shows as a block on the form. 该组件在表单上显示为块。 When you double click it, a panel appears showing you the contents inside that block. 双击它时,将出现一个面板,向您显示该块中的内容。 Both objects must be visible simultaneously and freely moveable from each other hence why it's not just a view change. 这两个对象必须同时可见并且彼此可以自由移动,因此为什么它不仅仅是视图更改。

My solution is to have a method that creates the bastard child object that is called from the main form after creating the Component object. 我的解决方案是创建一个创建混蛋子对象的方法,该子对象在创建Component对象后从主窗体调用。 Example: 例:

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

I agree that doing this is a bad design. 我同意这样做是一个错误的设计。 One way to accomplish this, however, is to override OnParentChanged() and create the "sibling" control there: 但是,一种实现此方法的方法是重写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);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM