I have recently experimented with WPF and MDI. Last time I used the Win32 API in order to create a WPF-based child window within a WinForms-based MDI parent window. It did some more research and came up with a more sophisticated solution.
The main problem remains: WPF does not (yet) provide build-in mechanisms for classic MDI management (besides from tab pages). So in order to use MDI (in my case I want to transform a WinForms-based MDI application into a WPF-based one), it is necessary to use a WinForms-based MDI parent window. The real question is how can you create a WPF window as a "real" MDI child.
Since all efforts failed so far, I decided to use a WinForms-based child window and search for ways to embed a WPF window within that window. There is a ElementHost-Control (WinForms) which can host WPF controls within a WinForms window. I intended to create WPF windows or pages and not WPF user controls, so I kept looking. Fortunately I found the Frame-Control (WPF) which can host content such as pages and that can be hosted within other WPF controls.
So putting it all together I created:
- WinForms MDI parent window (MDIParent)
- WinForms MDI child window (MDIChild) with a ElementHost-Control
- WPF user control (ucPageWrapper) embedding a Frame-Control
The following two code listings display the user control's XAML and C# code. As you can see it embeds a Frame-Control and its function "LoadContent" loads the page parameter into the frame.
<UserControl x:Class="ucPageWrapper"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Grid>
<Frame Name="Frame1" />
</Grid>
</UserControl>
public partial class UcPageWrapper : UserControl
{
public UcPageWrapper()
{
InitializeComponent();
}
public void LoadContent(Page page)
{
this.Frame1.Navigate(page);
}
}
The next listing shows the MDI child's code. It creates a new instance of the ucPageWrapper and passes the page parameter to it.
public partial class MDIChild : Form
{
public MDIChild()
{
InitializeComponent();
}
public void LoadContent(System.Windows.Controls.Page page)
{
UcPageWrapper control = new UcPageWrapper();
control.LoadContent(page);
this.elementHost1.Child = control;
}
}
Finally the code inside the MDI parent window. It creates a sample page Page1 and passes it as a parameter to a new MDI child.
Page1 page = new Page1();
MDIChild child = new MDIChild();
child.LoadContent(page);
child.MdiParent = this;
child.Show();
Full source code can be downloaded here.