0
votes

I am creating an application using WinForms. I have panel in which I show a user control. Inside this user control I have a button. When I click the button, I want to clear the panel and show a different user control. I am trying to do that using the following code:

private void btnCreateOffer_Click(object sender, EventArgs e)
{
    var myControl = new WindowsFormsDemo.View.CreateOffer();
    MockUpForm.panMain.Controls.Clear();
    MockUpForm.panMain.Controls.Add(myControl);
}

This works from the buttons placed directly in the parrent form, but when I use in inside the user control, it says:

'MockUpForm.panMain' is inaccessible due to its protection level

I suppose it has something to do with private/public classes. But I would rather have the "correct" solution, as opposed to just changing everything to public.

Any suggestions on how this is usually done?

2
It is a fundamentally wrong way to do this. Raise an event instead, your main form can subscribe it and jiggle around its controls. Using Controls.Clear() is also very, very wrong, you must call the Dispose() method on any control you remove or you'll cause a permanent memory leak.Hans Passant
Thanks for you comments. I am quite new to WinForms, so I am most likely doing a lot of stuff very wrong :-). I will look into the events method...Jakob Busk Sørensen
@HansPassant: He did not mention whether he wants to reuse the removed controls. But if events are also subscribed disposal is not enough, memory leak will occur anyway.György Kőszeg
That's not correct, disposing the removed controls is enough. The event only has a reference to the form object so could only keep the form object alive. It already is alive. The only reference that the form has to the control object is stored in the Controls collection, Dispose() removes it. No leak.Hans Passant
panMain.Dispose(); destroys the panel, which is not what you want. You should dispose each control in the panel, so try a while-loop: while (panMain.Controls.Count > 0) panMain.Controls[0].Dispose();LarsTech

2 Answers

1
votes

Solution 1 (ugly):

Make panMain public in the designer: modifiers

Solution 2 (somewhat better):

Provide public methods to achieve such tasks safely:

// MockUpForm code:

public void ClearPanelControls()
{
    panMain.Controls.Clear();
}

public void AddControlToPanel(Control c)
{
    panMain.Controls.Add(c);
}

And then call these methods instead of publishing the full panel, which makes possible for example to dispose the whole panel and such things...

1
votes

To access parent form's control from UserControl You can use delegate and event

something like this....

Windows Form (Parent Form) Code....

public Form1()
{
    InitializeComponent();
    userControl1.CreateOffer += UserControl1_CreateOffer;
}

private void UserControl1_CreateOffer()
{
    var myControl = new WindowsFormsDemo.View.CreateOffer();
    this.panMain.Controls.Clear();
    this.panMain.Controls.Add(myControl);
}

User Control Code...

internal delegate void CreateOfferDelegate();
internal event CreateOfferDelegate CreateOffer;

public UserControl1()
{
    InitializeComponent();
}

private void btnCreateOffer_Click(object sender, EventArgs e)
{
    CreateOffer();
}