简体   繁体   中英

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. I am not having a problem creating and displaying my UserControl on the form. Where I am having issues is creating a different type of UserControl and associating it with the first.

I have a class called HardwareComponent that is a child of the main form. 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. 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:

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

    public ComponentPanel()
    {

    }
}

*not shown are the OnPaint override methods

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. 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). 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. 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". 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. 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. 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:

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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