WPF in VSTO
Can you use WPF controls in VSTO solutions, and if so, how? VSTO's mission is to bring together the unmanaged Office platform and the managed development world. One aspect of this is the ability to build VSTO solutions that use managed controls within native Office windows. There are 5 places you can do this:
· Arbitrary Windows Forms custom dialogs
· Custom task panes in application-level add-ins
· The document actions pane in document-level solutions
· Custom form regions in Outlook inspectors
· The workbook or document surface in document-level solutions.
VSTO supports placing managed (Windows Forms) controls in each of these locations. The .NET Framework v3.5 includes support for hosting WPF controls within Windows Forms windows. Therefore, VSTO also supports placing WPF controls in each of these locations. The first one in this list is a no-brainer: clearly, if your solution is built in managed code, you can use managed dialogs. The next two are also no-brainers, because when you build app-level or doc-level custom task panes what you actually build is a custom Windows Forms UserControl, which you then hand off programmatically to the VSTO runtime to site within the native window that Office supplies. It might be less obvious, but the fourth case is also the same: Visual Studio 2008 provides design-time support for custom form regions, including a FormRegionControl designer. This is based on the familiar Windows Forms UserControl designer, and the VSTO FormRegionControl class derives from the Windows Forms UserControl class. The VSTO infrastructure then seamlessly hooks up this control to the native Outlook window at runtime on your behalf.
The last remaining case is managed controls on the document surface. This only applies to Word and Excel, because these are the only apps that VSTO provides doc-level solution support for. Since Visual Studio 2005, you've been able to put any arbitrary managed control onto the document surface. So, the question is, can you now do this with WPF controls in Visual Studio 2008?
The answer is a qualified "Yes".
You can put WPF controls in all 5 locations programmatically. Visual Studio 2008 – even in the CTP/beta releases – provides some level of design-time support for all cases. The level varies, but the support for say custom form regions is very comprehensive and a joy to use. The .NET Framework 3.5 includes a WindowsFormsIntegration.dll which provides a number of useful classes for integrating Windows Forms and WPF, in both directions. So, you can create a custom Windows Forms UserControl at design-time and drag+drop a WPF control onto the UserControl design surface. This will automatically generate a Windows Forms Integration ElementHost class to host the WPF control. You will be able to work with the WPF control, the ElementHost control and the Windows Forms control in the designer.
However, VS 2008 does not provide design-time support for placing WPF controls on the surface of a Word or Excel document. This is mainly because the VSTO doc-level designers for Word and Excel are somewhat challenging beasts, as I'm sure you can imagine, and making any enhancements to them involves a lot of head-scratching, eye-rolling and nose-twitching (and not the Elizabeth Montgomery kind – now, that would be a useful development tool… but I digress).
So, if you want to put a WPF control onto the document surface, you can use the regular design-time support for building a Windows Forms control that incorporates your WPF control, but then you have to stop short of actually putting the control on the document surface at design-time, because the VSTO designers don't support it. This applies both to the WPF control and to the Windows Forms control that you've built to host the WPF control – right now, neither will work on the VSTO designers.
That said, doing it programmatically is really no effort at all. The VSTO infrastructure already supports any arbitrary Windows Forms control, including controls that host WPF controls. The runtime is already in place, and has been since Visual Studio 2005. So, the only programmatic piece you have left to do is to instantiate the outer Windows Forms control (that's hosting your WPF control, via ElementHost) and add it to the solution.
private void Sheet1_Startup(object sender, System.EventArgs e)
string controlName = "MyWfControl";
WfControl wfControl = new WfControl();
wfControl.Tag = Controls.AddControl(wfControl, 50,50, 200,250, controlName);
wfControl.Name = controlName;
In this example, my Windows Forms control type is WfControl. I use one of the overloads of AddControl to hook up this control with the document surface via the VSTO infrastructure, and… that's it! If you think about it, this model is really the same as for custom task panes and document actions panes: you do some initial designer work, using Windows Forms designers, and then manually type in a couple of lines of code.