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 (19)

  1. Anonymous says:

    Any plans to support managed Windows Forms controls on the workbook/document surface in application level add-ins?

  2. Garry Trinder says:

    Yes, the ability to use VSTO document-level functionality from VSTO app-level add-ins is something we are considering very seriously. We certainly recognize the need for this feature, and I would certainly like to provide the necessary support for this. Right now, you can’t do this, and it is not a feature in the upcoming VS 2008 release. Although I can’t make any promises, I’m keeping it on our TODO list as a high priority.

  3. Anonymous says:

    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!!!

  4. Anonymous says:

    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?

  5. Anonymous says:

    Hi,

    Thanks for the explination. However I cant load Element Host or WPF controls directly onto the suface of the Word Document, am I doing some very wrong. Dont even have the Elment Host control available. And when i access it programmatically I get WFControl? Missing assmebly?? Any ideas? thanks

    James

  6. Garry Trinder says:

    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

  7. Anonymous says:

    Thanks, I sold my problem just a matter of re-installing VSTO 3.0??? Not sure why but solved the problem, however I am now facing a alternative problem with an emmbeded WPF Web Browser Control when loaded into an Activity Pannel. I get the error during loading of the Excel template:

    Could not load type ‘System.Windows.Controls.WebBrowser’ from assembly ‘PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’.  Error in markup file ‘AldersfordeltTemplate;component/activitypannel.xaml’ Line 1 Position 14.

    Any ideas?

  8. Garry Trinder says:

    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.

  9. Anonymous says:

    Hi Andrew, (This is strange)

    Well after some serious investigation and head banging debugging, I have found the root of my problem. Wait for it… Its an interesting one.

    Try programatically creating smart tags for just any reason. Then trying using WPF Web Browser control inside your WPF Control hosted in a Task Pane or Activity Panel for that matter. The error was actually incorrect above I wasnt catching it properly but bellow is a description.

    The following error occures during the display (not loading?!?!?) of the Element host or the WPF Control, but when it is actually displayed in the Activity Panel/Task Pane.

    The only exception detail I can get from the inner expection is the thrown:

    System.Windows.Interop.HwndHost.BuildWindow(HandleRef hwndParent)

    If I remove the programatic creation of smart tages, hey presto thing works again???

    Any ideas

    James

  10. Garry Trinder says:

    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?

  11. Anonymous says:

    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

  12. Garry Trinder says:

    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.

  13. Anonymous says:

    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

  14. Anonymous says:

    Sorry in Outlook 2007.

    Long night.

    James

  15. Garry Trinder says:

    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?

  16. Anonymous says:

    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.

    Thanks

    James

  17. Garry Trinder says:

    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.

  18. Anonymous says:

    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

  19. Anonymous says:

    Hi Andrew,

    Hope you had a nice easter. Really scratching my head at the moment with something.

    I am trying to send a Parameter from Querystring to a word document. I have a content type in MOSS and want to pass a parameter to the load event on the form to populate some metadata.

    Any ideas?

    James