Sharing a Ribbon Office 2010 and Visual Studio 2010
-
Friday, June 04, 2010 8:52 PM
I'm working on upgrading a solution from Visual Studio 2008 to 2010 to support the Office 2010 template types for Outlook and whatnot. I have things set up as outlined here:
http://blogs.msdn.com/b/vsto/archive/2008/03/10/share-a-ribbon-customization-between-office-applications.aspxMultiple AddIn projects which reference a shared assembly that has a ribbon defined in it.
After upgrading the solution to Visual Studio 2010 I no longer get the Visual Ribbon Designer interface. I'm getting an exception citing an incorrect parameter:
The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))
at EnvDTE.Properties.Item(Object index)
at Microsoft.VisualStudio.Tools.Office.Ribbon.Helpers.GetTargetOfficeVersion(IDesignerHost host)
at Microsoft.VisualStudio.Tools.Office.Ribbon.View.RibbonView.InitializeTheme()
at Microsoft.VisualStudio.Tools.Office.Ribbon.View.RibbonView.set_Site(ISite value)
at System.ComponentModel.Container.Add(IComponent component, String name)
at System.ComponentModel.Design.DesignerHost.PerformAdd(IComponent component, String name)
at System.ComponentModel.Design.DesignerHost.System.ComponentModel.Design.IDesignerHost.CreateComponent(Type componentType, String name)
at System.ComponentModel.Design.Serialization.DesignerSerializationManager.CreateInstance(Type type, ICollection arguments, String name, Boolean addToContainer)
at System.ComponentModel.Design.Serialization.DesignerSerializationManager.System.ComponentModel.Design.Serialization.IDesignerSerializationManager.CreateInstance(Type type, ICollection arguments, String name, Boolean addToContainer)
at Microsoft.VisualStudio.Tools.Office.Ribbon.Serialization.TypeResolutionModifications.VSTDesignerSerializationManager.CreateInstance(Type type, ICollection arguments, String name, Boolean addToContainer)
at System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
at Microsoft.VisualStudio.Tools.Office.Ribbon.Serialization.RibbonTypeCodeDomSerializer`1.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)
at System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)
at Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)
at System.ComponentModel.Design.Serialization.BasicDesignerLoader.BeginLoad(IDesignerLoaderHost host)Has anyone else encountered this issue and found a resolution? Is there another suggested practice for sharing a Ribbon between multiple projects in Visual Studio 2010? Thanks in advance for any guidance that anyone can provide.
All Replies
-
Friday, June 04, 2010 9:47 PMAnswerer
Note that the blog post you're referring to is a scenario that happened to work in Visual Studio 2008, but it was not a stricly supported feature that was designed into the product, so there is no guarantee that it would work in the next release of Visual Studio.
I tried the steps in the blog post in Visual Studio 2010 for two sets of projects, one that targets .NET Framework 3.5 and another that targets .NET Framework 4. In both cases, I was able to reproduce the error when you open the Ribbon file in the class library project. From the stack trace, it appears that cause of the error is an implementation change in the Ribbon designer in Visual Studio 2010. When you try to open a Ribbon file in Visual Studio 2010, it tries to call into the current project to get the version of Office that the project targets. Since the current project is a class library project instead of an Office project, this call fails and hence the crash. That said, I believe the product team might say this is by design, since these Ribbon code files were only designed to be opened/used in the context of Office projects.
That said, I was able to get the process to work when targeting .NET Framework 3.5 by doing all of the visual design work in the Ribbon designer in the first Office project, and then adding the Ribbon code file to the class library project only after finishing my edits to the files. From then on, everything works as expected, provided that I didn't try to double-click the Ribbon code file in the class library project to open the designer (you can safely right-click the file and choose View Code, however).
When targeting .NET Framework 4, I wasn't able to get the process working at all, due to several changes in the programming model for Office projects that target the .NET Framework 4. Due to these changes, the code-behind file for the Ribbon contains several references to several items in the Office add-in project (such as Globals) that do not get ported over when you add the Ribbon file to the class library project. I will try to follow up with the product team to see if there might be some other way to get this scenario to work for Office add-ins that target the .NET Framework 4.
This posting is provided "AS IS" with no warranties, and confers no rights.- Marked As Answer by Tim LiModerator Thursday, June 10, 2010 6:16 AM
-
Saturday, June 05, 2010 4:56 PMThankyou for the very detailed response. I'm very curious as to whether there is another recomendation for sharing a ribbon between addins. In this case I'm working with boith Office 2007 and Office 2010.
- Edited by CaseyMargell Saturday, June 05, 2010 4:57 PM Typo
-
Wednesday, June 16, 2010 7:22 PM
Hi McLean,
Were you able to follow up with the product team to see if there is a suggested approach for sharing a ribbon in VS2010 and/r .Net 4?
Thanks,
Casey
-
Wednesday, June 16, 2010 7:34 PMAnswerer
Yes, and I'm writing up a blog post soon with the information. Here are the new steps for doing this in Office projects that target the .NET Framework 4 in Visual Studio 2010. Note again that this is unsupported, has not been officially tested by the product team in any way, etc - but "should" work.
1. Create an Office project targeting .NET Framework 4.
2. Add a Ribbon Designer item. Design your Ribbon, make any controls/tabs/groups you want to access public, and set the RibbonType property for all Ribbon types you want to support in other Office projects that consume the shared Ribbon. Save your changes. Note that you must design your Ribbon here if you want to use the Ribbon designer.
3. Create a class library project targeting .NET Framework 4. Add following references:
· Microsoft.Office.Tools
· Microsoft.Office.Tools.Common
· Microsoft.Office.Tools.Common.v4.0.Utilities
4. Add the existing Ribbon code file to the class library project. Open the Ribbon file and code-behind file (e.g., Ribbon1.Designer.cs) in the code editor (do not double-click the files; this will attempt to open the Ribbon designer, and will result in a designer error).
5. In the Ribbon code-behind file, change the constructor to the following.
public Ribbon1(Microsoft.Office.Tools.Ribbon.RibbonFactory factory)
: base(factory)
{
InitializeComponent();
}
6. In Ribbon code-behind file, remove the ThisRibbonCollection class definition at the bottom of the file.
7. Optionally, change the namespaces for the Ribbon class in the main Ribbon file and code-behind file (to SharedRibbonLibrary or whatever identifies your component).
8. Build the class library project.
9. In a new/different Office project that targets the .NET Framework 4, add a reference to the class library project.
10. Override CreateRibbonObjects as follows (following code assumes you changed the namespace of the shared Ribbon to SharedRibbonLibrary).
protected override Microsoft.Office.Tools.Ribbon.IRibbonExtension[] CreateRibbonObjects()
{
return new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { new
SharedRibbonLibrary.Ribbon1(Globals.Factory.GetRibbonFactory()) };
}
11. Add the following class to the project, so that you can access the shared Ribbon customization from Globals.Ribbons.
partial class ThisRibbonCollection : Microsoft.Office.Tools.Ribbon.RibbonReadOnlyCollection
{
internal SharedRibbonLibrary.Ribbon1 Ribbon1
{
get { return this.GetRibbon<SharedRibbonLibrary.Ribbon1>(); }
}
}
12. Now you can use Globals.Ribbons.Ribbon1 to access public items exposed by the shared Ribbon. For example:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Globals.Ribbons.Ribbon1.button1.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(button1_Click);
}
void button1_Click(object sender, Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs e)
{
System.Windows.Forms.MessageBox.Show("it works!");
}
This posting is provided "AS IS" with no warranties, and confers no rights.- Marked As Answer by CaseyMargell Wednesday, June 16, 2010 9:59 PM
-
Wednesday, June 16, 2010 10:00 PMYou rock! Thankyou so much for the information, can you post a link once your post is up as well?
-
Wednesday, June 23, 2010 6:51 PMAnswerer
This posting is provided "AS IS" with no warranties, and confers no rights.

