Here's an outline of a strategy ... within an MDI WinForms flavor app ... for using three Forms. The structure:
a. a Form named 'TheMdiParentForm which has its 'MDIParent Property set to 'true
a.1 two Forms, 'DefaultChildForm, and 'ChildForm1
a.1.1 'DefaultChildForm is the Form you want to appear occupying all the client area of TheMDIParentForm
a.1.2 'ChildForm1 is the "other" Form that you want to appear "on demand."
a.1.3. instances of both of these Forms are declared at Form scope
Design-time:
Both child Forms have their 'ControlBox properties set to false, so the user cannot close them at run-time in the usual way.
Initial state:
b. when TheMdiParentForm loads:
b.1. instances of 'DefaultChildForm and 'ChildForm1 are created and assigned to the instances created in a.1.3: their 'MdiParent property is set to 'TheMdiParentForm
b.1.1. the instance of 'DefaultChildForm is shown full-screen in the client area of TheMdiParentForm
b.1.1.1 a button, 'ChildForm1OpenButton' on this Form: will make 'ChildForm1 visible, and then hide the 'DefaultChildForm
b.1.2. the instance of 'ChildForm1 has its visible property set to 'false: is not shown.
b.1.2.1 a button 'ChildForm1CloseButton on this Form: closes the Form
Run-time behavior
c.1 the user clicks the 'Open button on the 'DefaultChildForm: it is hidden, and 'ChildForm1 is displayed.
c.2 the user clicks the 'Close button on ChildForm1: it is hidden, and the DefaultChildForm is displayed.
c.3 the user clicks the standard Windows Close CheckBox on the TheMdiParentForm: the application terminates.
Notes:
a. Whatever you wanted to use in the 'Panel you mention is put on the 'DefaultChildForm.
b. you will have to deal with passing back any data you require from either of the two Child Forms to the main MdiForm. I strongly recommend you do not implement passing any data between the 'DefaultChildForm and the 'ChildForm1 directly.
So, how do we implement this "communication" between Child Forms and MdiParent ?
a. in 'ChildForm1's code:
public Action CloseButtonClick { set; get; }
private void ChildForm1CloseButton_Click(object sender, EventArgs e)
{
if (CloseButtonClick != null) CloseButtonClick();
}
b. in 'DefaultChildForm's code:
public Action OpenButtonClick { set; get; }
private void ChildForm1OpenButton_Click(object sender, EventArgs e)
{
if (OpenButtonClick != null) OpenButtonClick();
}
In the MDIParent's code:
private DefaultChildForm DefaultChildFormInstance = new DefaultChildForm();
private ChildForm1 Child1FormInstance = new ChildForm1();
private void TheMdiParentForm_Load(object sender, EventArgs e)
{
DefaultChildFormInstance.MdiParent = this;
DefaultChildFormInstance.OpenButtonClick += OpenButtonClick;
DefaultChildFormInstance.Show();
Child1FormInstance.Visible = false;
Child1FormInstance.MdiParent = this;
Child1FormInstance.CloseButtonClick += CloseButtonClick;
}
private void CloseButtonClick()
{
Child1FormInstance.Hide();
DefaultChildFormInstance.Show();
}
private void OpenButtonClick()
{
DefaultChildFormInstance.Hide();
Child1FormInstance.Show();
}
How does this work ?
a. we inject two simple Delegates (Type Action) into the instances of the two Child Forms. When the Button is clicked in either of those Child Forms, the Delegate instance we injected is executed, and our Event Handlers defined in the MdiParentForm are called.
How would we return data from either of the Child Forms to the MdiParentForm: we could use a similar technique of defining a Public Delegate in the Child Forms ... or defining Public structures, or even a Class, in the Child Forms.
How would we "signal" the MdiParentForm that we had some valid data to be returned: we could easily change our Action Delegate to pass back a boolean parameter: in ChildForm1:
private HasData = false;
public Action<bool> CloseButtonClick { set; get; }
private void ChildForm1CloseButton_Click(object sender, EventArgs e)
{
if (CloseButtonClick != null) CloseButtonClick(HasData);
}</bool>
And, modify the MdiParentForm to recognize when data is available:
private void CloseButtonClick(bool hasData)
{
if (hasData)
{
data.Clear();
data = Child1FormInstance.GetData();
}
Child1FormInstance.Hide();
DefaultChildFormInstance.Show();
}
In the above code, a Delegate Type Func is called in the instance of the ChildForm1: it looks like this:
public Func<List<string>> GetData { set; get; }
private void ChildForm1_Load(object sender, EventArgs e)
{
GetData = () => { return data; };
}
This Func Delegate ... that takes no parameters and returns a List of Type String ... is set in the ChildForm1 Load EventHandler to return the current 'data; in this code it is set using the 'lambda notation "shorthand" ... an anonymous method is created and bound to the 'Func.