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.
Comments
- Anonymous
August 16, 2007
Any plans to support managed Windows Forms controls on the workbook/document surface in application level add-ins? - Anonymous
August 22, 2007
The comment has been removed - Anonymous
August 30, 2007
Hi Andrew;We have an Excel Template solution developed using Visual Studio Tools for Office 2005 that has a custom control on the Action Pane. When the user clicks on a link in IE the Excel document will be generated on the server and sent to client browser. On the browser side, Excel will load the document and the Action Pane with the custom control will show as expected. Normally the user will need to work with more than one document at a time by clicking a second link and loading the next excel document with the previous document still on display. The problem we are having now is that the second excel document will be loaded without any errors but the Action Pane contains no custom controls. So what we have here is that only the first document with the expected Action Pane; the rest of the documents with an empty Action Pane. Our tests indicate that the event ThisWorkbook_Startup for the second instance forward has never been fired which explains why the custom controls weren’t loaded. What makes it interesting is that when we used Mozilla Firefox browser everything works. With Firefox, we can have multiple excel workbooks each with its own custom Action Pane. What we couldn’t figure out was how to make it work in IE. Please help!!! - Anonymous
October 08, 2007
Isn’t a bit too heavy hosting a WPF control inside a Windows Forms control, that is hosted inside an ActiveX control to Microsoft can display it in the task pane for example, and that is hosted in a Win32 control?Why simply word does not host WPF natively? - Anonymous
July 30, 2008
The comment has been removed - Anonymous
July 31, 2008
James - if you get an error message telling you you're missing an assembly, then you're probably missing an assembly. :-) Seriously, though, as I mention in my post, this technique requires VS 2008 and .NET Framework 3.5. If you don't have .NET 3.5, you can download it from here: http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6&displaylang=en - Anonymous
September 26, 2008
The comment has been removed - Anonymous
September 26, 2008
James - it looks like your "Activity Panel" is a WPF control or window. In which case, there should be no problem loading the WPF WebBrowser control into it. What happens if you create a very simple WPF application, and put the WebBrowser control in it? If that works, then you've probably got all the right runtime pieces in place - so then it would point to a problem in your code somewhere. - Anonymous
September 29, 2008
The comment has been removed - Anonymous
September 30, 2008
James - I'm not clear on what you're doing. Are you creating a doc-level solution or an app-level add-in? Are you putting your hosted WPF control onto a doc-level ActionsPane or an app-level Custom TaskPane? What is this "Activity Panel" you mention? - Anonymous
October 06, 2008
Hi Andrew,I am creating a Document level addin. So I am hosting the WPF control in a ActionsPane using the Element Host control.Sorry the activity pannel is the Name of the WPF Control i have created, so that was a error in naming above.Thanks - Anonymous
October 14, 2008
James - I've investigated this and I have in fact managed to reproduce the error you got. So, this looks like a bug - we'll do some more investigation and figure out what the correct fix is. Thanks for your input. - Anonymous
December 18, 2008
Hi Andrew,Just quickly, Im trying to reference the built in web browser control itself not the control that sends URL param´s to it...Any ideas?James - Anonymous
December 18, 2008
Sorry in Outlook 2007.Long night.James - Anonymous
December 27, 2008
James - I'm confused. This is a new project you're talking about, right? (That is, not related to the Word ActionsPane/WPF WebBrowser project.)So, in your Outlook project, you're trying to reference which control? The System.Windows.Forms.WebBrowser or the System.Windows.Controls.WebBrowser?...and where are you trying to place this control? - Anonymous
January 03, 2009
Hi,Happy new year.Yes sorry, its a totally new project. I have an outlook addin that is trying to reference the existing web browser in outlook.As you know there is the abilty to browse the web in Outlook. I want to get at this pre-built exsiting control to hook into its events.ThanksJames - Anonymous
January 04, 2009
James - Happy New Year to you too!Unfortunately, the Outlook object model does not expose any formal way of getting hold of the internal web browser (which btw, is just IE - specifically ieframe.dll). However, there is at least one way to do this - see Sue Mosher's OutlookCode site: http://www.outlookcode.com/codedetail.aspx?id=1496. - Anonymous
January 04, 2009
Hi,Yeah i already tried something like this:Office.CommandBarComboBox webCtrl =(Office.CommandBarComboBox)this.Application.ActiveExplorer().CommandBars.FindControl(26, 1740, missing, missing);webCtrl.Text = "www.m2c.no";However the change event doesnt fire consitently :(...oh well back to the drawing board... thanks - Anonymous
April 15, 2009
The comment has been removed