Question

In C# i want to create a panel that has the properties of a MDI container ie. isMdiContainer = true.

I tried something like this

form.MDIParent = this.panel1;

But that dont work. Any suggestions?

Was it helpful?

Solution

You could create custom form, remove all borders, and toolbars to make it look as closely to a panel as possible. Then make that new custom form a MdiContainer.

Basically, you can only set the IsMDIContainer property on a Form. This means that only a form can be a MdiContainer.

OTHER TIPS

It is possible to create an MDI-panel and show forms in that panel, something like the code below will do the job

Mdi-Panel definiton:

public class MdiClientPanel : Panel
{
    private Form mdiForm;
    private MdiClient ctlClient = new MdiClient();

    public MdiClientPanel()
    {
        base.Controls.Add(this.ctlClient);
    }

    public Form MdiForm
    {
        get
        {
            if (this.mdiForm == null)
            {
                this.mdiForm = new Form();
                /// set the hidden ctlClient field which is used to determine if the form is an MDI form
                System.Reflection.FieldInfo field = typeof(Form).GetField("ctlClient", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                field.SetValue(this.mdiForm, this.ctlClient);
            }
            return this.mdiForm;
        }
    }
}

Usage:

/// mdiChildForm is the form that should be showed in the panel
/// mdiClientPanel is an instance of the MdiClientPanel
myMdiChildForm.MdiParent = mdiClientPanel1.MdiForm;

I used Mathias's answer above and was able to get rid of most of the issues raised in the comments. I created a helper class for the child forms as well, in case anyone wanted to use it and/or make it better.

    public class MdiClientPanel : Panel
{
    private MdiClient _ctlClient = new MdiClient();

    // Callback event when a child is activated
    public delegate void ActivateHandler(object sender, MdiClientForm child);
    public event ActivateHandler OnChildActivated;

    /// <summary>
    /// The current active child form
    /// </summary>
    public Form ActiveMDIWnd
    {
        get;
        set;
    }

    /// <summary>
    /// List of available forms
    /// </summary>
    public List<MdiClientForm> ChildForms = new List<MdiClientForm>();

    /// <summary>
    /// Std constructor
    /// </summary>
    public MdiClientPanel()
    {
        base.Controls.Add(_ctlClient);
    }

    private Form _mdiForm = null;
    public Form MdiForm
    {
        get
        {
            if (_mdiForm == null)
            {
                _mdiForm = new Form();
                // Set the hidden _ctlClient field which is used to determine if the form is an MDI form
                System.Reflection.FieldInfo field = typeof(Form).GetField("ctlClient", 
                    System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

                field.SetValue(_mdiForm, _ctlClient);
            }
            return _mdiForm;
        }
    }

    private void InitializeComponent()
    {
        SuspendLayout();
        ResumeLayout(false);
    }

    /// <summary>
    /// Add this Form to our list of children and set the MDI relationship up
    /// </summary>
    /// <param name="child">The new kid</param>
    /// <returns>The new kid</returns>
    public MdiClientForm AddChild(MdiClientForm child)
    {
        child.MyMdiContainer = this;
        child.MdiParent = MdiForm;
        ChildForms.Add(child);

        return child;
    }

    /// <summary>
    /// The user sent a "restore" command, so issue it to all children
    /// </summary>
    public void RestoreChildForms()
    {
        foreach (DataTableForm child in ChildForms)
        {
            child.WindowState = FormWindowState.Normal;
            child.MaximizeBox = true;
            child.MinimizeBox = true;
        }
    }

    /// <summary>
    /// Send the Activated message to the owner of this panel (if they are listening)
    /// </summary>
    /// <param name="child">The child that was just activated</param>
    public void ChildActivated(MdiClientForm child)
    {
        ActiveMDIWnd = child;

        if (OnChildActivated != null)
            OnChildActivated(this, child);
    }

    /// <summary>
    /// The child closed so remove them from our available form list
    /// </summary>
    /// <param name="child">The child that closed</param>
    public void ChildClosed(MdiClientForm child)
    {
        ChildForms.Remove(child);
    }
}

/// <summary>
/// A wrapper class for any form wanting to be an MDI child of an MDI Panel
/// </summary>
public class MdiClientForm : Form
{
    /// <summary>
    /// My parent MDI container
    /// </summary>
    public MdiClientPanel MyMdiContainer { get; set; }

    /// <summary>
    /// Standard Constructor
    /// </summary>
    public MdiClientForm()
    {
        Activated += OnFormActivated;
        FormClosed += OnFormClosed;
    }

    /// <summary>
    /// Reports back to the container when we close
    /// </summary>
    void OnFormClosed(object sender, FormClosedEventArgs e)
    {
        MyMdiContainer.ChildClosed(this);
    }

    /// <summary>
    /// Reports back to the parent container when we are activated
    /// </summary>
    private void OnFormActivated(object sender, EventArgs e)
    {
        MyMdiContainer.ChildActivated(this);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top