Scenario: You created an add-in for Microsoft Office Outlook 2007, including a custom form region and a Ribbon customization. You built it using Microsoft Visual Studio 2008 Tools for the 2007 Microsoft Office system and the Microsoft .NET Framework 3.5. Now, given Microsoft Visual Studio 2010 and the new .NET Framework, you want to update your add-in to target the new version of the .NET Framework. It's easy to modify the target version of .NET, but you find that by doing this you caused your add-in not to compile. You need to modify the code slightly to utilize the new interface-based features in the Office Extensions for the .NET Framework 4.0.
The sample that is included with this article includes a working Outlook 2007 add-in, created with Visual Studio 2008 Tools for Office. This add-in targets the NET Framework 3.5, and it includes two features. The add-in provides a custom form region, shown in Figure 1, which displays data from the Northwind sample database in SQL Server, and allows you to select a customer and an order number when you create a new email message.
Given that information, when you click Insert, you create and format the address and body of the email message. The Ribbon customization, shown in Figure 2, allows you to select a Northwind customer from a Menu control. Once you select a customer, the customization inserts an email address for the selected customer into the To address field. You may find the internal code for the add-in to be of interest, but it's not the focus of this article. Instead, this article focuses on how to migrate this add-in so that it targets the .NET Framework 4.0.
Targeting the .NET Framework 4.0 allows you to take advantage of the fact that the Office Extensions for .NET 4.0 use a runtime that is version-resilient, based on interfaces instead of classes. Combined with type embedding, this makes your solution much less dependent on the version of Office installed on end user computers. For more information about the benefits of upgrading your add-in so that it targets the .NET Framework 4.0, see the links in the Explore It section.
Figure 1. With CustomFormRegion, you can select information about a customer and insert it into an email message
Figure 2. The Ribbon customization allows you to select a customer and insert the corresponding email address
Download the sample code
Follow these steps to convert the add-in so that it targets the .NET Framework 4.0.
To set the target version
In Visual Studio 2010, in the Solution Explorer window, right-click the project node and select Properties from the context menu.
In the Properties window, for Microsoft Visual Basic, select the Compile tab and then the Advanced Compile Options button. For both Microsoft Visual Basic and Microsoft C#, set the Target framework property to .NET Framework 4 Client Profile. The Client Profile option sets the project up for client-side use, and includes references to fewer assemblies than are added by selecting the .NET Framework 4 option. When you are prompted to close and re-open the project so that Visual Studio can change the Target Framework, click Yes.
Save and compile the project. You'll find that the project, which originally compiled and ran fine, now returns many errors that you must fix.
To fix the Form Region
If your current Visual Studio configuration does not let you expand the node that corresponds to CustomerFormRegion.vb or CustomerFormRegion.cs, select Project and then Show All Files to display all the files in the project.
Expand the CustomerFormRegion.vb or CustomerFormRegion.cs node, and double-click CustomerFormRegion.Designer.vb or .cs, displaying the code in the Code Editor.
In .NET 4.0 projects, a form region inherits from FormRegionBase, instead of FormRegionControl: In the Code Editor, change the declaration of the CustomerFormRegion class so that it inherits from Microsoft.Office.Tools.Outlook.FormRegionBase, instead of Microsoft.Office.Tools.Outlook.FormRegionControl.
Because the new Office extensions are based mostly on interfaces, instead of classes, you cannot simply create instances of objects as you need them. Instead, you must rely on the class factories that are provided by the framework to do the job for you. Modify the constructor for the class so that it looks like the following code.
: base(Globals.Factory, formRegion)
The FormRegionBase class defines its InitializeManifest procedure slightly differently. Therefore, modify the signature for InitializeManifest so that it looks like the following (do not modify the code inside the procedure, which is fine as it is). In C#, expand the Form Region Designer Generated Code block first.
private static void InitializeManifest(
Some code changes are too complex to manage manually. It is simpler to add a new Form Region to the project, and copy the code from the new template. To accomplish this goal, start by selecting Project, and then Add New Item. Select Outlook Form Region and accept the default name, FormRegion1.
Click Next to accept the defaults in every page of the Wizard, and then click Finish when it becomes enabled.
In the Solution Explorer window, expand the FormRegion1.vb or .cs node, and double-click FormRegion1.Designer.vb or .cs, loading it in the Code Editor.
Find and select both the FormRegion1Factory and WindowFormRegionCollection classes. Copy the selection to the clipboard, and replace CustomerFormRegionFactory and WindowFormRegionCollection with the contents of the clipboard in the CustomerFormRegion class. (The names are wrong in the copied code; you will fix those in the next step.)
Search and replace all instances of FormRegion1 with CustomerFormRegion in the current document.
Delete the sacrificial FormRegion1 object from the Solution Explorer window.
In Visual Basic, in the WindowFormRegionCollection class, modify the CustomerFormRegion property so that it converts the return value to the CustomerFormRegion type before it returns the reference.
For Each Item As Object In Me
If (TypeOf (Item) Is CustomerFormRegion) Then
Return CType(Item, CustomerFormRegion)
To fix the Ribbon customization
In the Solution Explorer window, expand Ribbon1.vb or .cs, and double-click Ribbon1.Designer.vb or .cs to open it in the Code Editor.
Modify the Ribbon1 class so that it inherits from the RibbonBase class instead of the OfficeRibbon class.
Modify the class' constructor so that it calls the Globals.Factory.GetRibbonFactory method in the base class.
Because all the elements that you put on Ribbon customizations are now based on interfaces, instead of classes, you must call the appropriate factory method to hand you an instance of the corresponding Ribbon control. In your own code, you will need to find any location in which you create an instance of a control. In the sample, in Ribbon1.Designer.vb or .cs, find the InitializeComponent procedure. (In C#, expand the Component Designer generated code block first.)
Replace the three lines in the sample that create instances of controls with the following code, which calls the correct factory method for each control type.
this.TabCustom = this.Factory.CreateRibbonTab();
this.customersGroup = this.Factory.CreateRibbonGroup();
this.customerMenu = this.Factory.CreateRibbonMenu();
Find the ThisRibbonCollection class, and modify the class so that it no longer inherits from the RibbonReadOnlyCollection class.
In C#, you must replace all event handler declarations with new, generic delegates. The simplest way to do this is to create a new blank line, type the event name, type the += operator, and allow the editor to create the new delegate instance. In the sample, find the line of code that sets up the this.Load event handler, create a blank line, and let the editor generate the new event handler hookup for you. Delete the original when you're done. The new code looks like the following.
this.Load +=new Microsoft.Office.Tools.Ribbon.
Finally, find any code that instantiates Ribbon controls outside the designer class, and call the appropriate factory method to create the instance instead. In the Ribbon class itself, you can call Factory.Create<ControlType>. In other classes, you can use the Globals.Factory instance, calling the Create<ControlType> method. In the sample project, in the Solution Explorer window, right-click the Ribbon1 project item and select View Code from the Context menu. Replace the code that instantiates a RibbonButton control with the following code.
RibbonButton item = Factory.CreateRibbonButton();
If you have followed the steps carefully, you can now compile and run the modified version of the sample Outlook add-in.
The example you have seen here includes many of the issues that you will encounter when you update your own add-ins to target the .NET Framework 4.0, but clearly, you will have other issues as well. Review the documents listed in the Explore It section where you will find complete documentation on the kinds of issues you're likely to encounter in addition to full documentation on the new factory methods and other important information.
You may find it simpler to start from scratch. That is, it may be easier to re-create the user interface for your custom form region and Ribbon customizations. This allows the Visual Studio 2010 designer to create the appropriate code for you. Then, you can copy over your own code, and fix up any minor issues that you find. For a large and complex customization, this may be a simpler solution.
Watch the Video
Video Length: 9:52
File Size: 14.6 MB WMV
About the Author
Ken Getz (MVP) is a developer, writer, and trainer, working as a senior consultant with MCW Technologies, LLC. In addition to writing hundreds of technical articles over the past fifteen years, he is lead courseware author for AppDev (http://www.appdev.com). Ken has co-authored several technical books for developers, including the best-selling ASP.NET Developer's Jumpstart, Access Developer's Handbook series, and VBA Developer's Handbook series. Ken is a member of the INETA Speakers Bureau, and speaks regularly at a large number of industry events, including 1105 Media's VSLive, and Microsoft's Tech-Ed.