Launching Modal WPF Windows from Windows Forms Apps...It's Magically Delicious!

(Blogging Tunes: Al Green - "The Absolute Best (Disc 1)")

Ah you can't beat the sweet soulful sounds of The Reverend Al Green now can you?  Anyhoo, I received a message from a customer a while back wanting help with launching a modal WPF window from a Windows Forms application.  The basics are really quite straightforward.  All you have to do is create an instance of your WPF window object and then call the ShowDialog() method on the window object and you will have launched a modal WPF dialog.

Window1 w = new Window1();
w.ShowDialog();

That seems simple enough, is that all there is to it?  Well, not quite.  If you use the code snippet above the WPF window certainly pops up and seems to act like a modal window...that is until you try to minimize it or the application itself.  Normally, when you minimize a modal window, the parent window gets minimized as well.  And when you restore either window, both windows get restored.  But using the code above will result in improper modal behavior.  What happens is that when you restore one of the windows, only that window is restored.  Not what we want.

The problem stems from the fact that we don't have our window parenting correct.  I guess you could think of it as bad (window) parenting, which means we can refer to this as a "deadbeat window".  Well, why can't we just set the Owner property of the WPF window to our main window and be done with it?  You can't do that because the Owner property of the WPF window is of type System.Windows.Window and the Windows Forms Form is not of that type.  It's of type System.Windows.Forms.Form.  So how can we get this geneological problem resolved and see to it that we have a successful adoption process?

There's a little helper class known as WindowInteropHelper which lives in a glade by the woods known as the System.Windows.Interop namespace.  Think of this little guy as a magic leprechaun.

No, not like that one...more like this one:

So using this helper class you can get this to work.  Change the code snippet above to the following:

Window1 w = new Window1();

WindowInteropHelper helper = new WindowInteropHelper(w);
helper.Owner = this.Handle;

w.ShowDialog();

This allows us to set the Owner property of the WPF window to the handle of our main form and both of these are of the correct type (IntPtr).  Now things just work as we expect them to.