title: Problem with custom web part adding contextual ribbon tab
body: <p>Follow the example illustrated in <a href="http://blog.dennus.net/2010/07/20/ribbon-buttons-with-postback-in-sp2010/" rel="nofollow">http://blog.dennus.net/2010/07/20/ribbon-buttons-with-postback-in-sp2010/</a>, rather than using declarative approach in this example, I created custom web part class and registered ribbon data extension, pageComponent script and etc. during OnPreRender event.</p>
  
  <p>Everything appears to be working just fine, I got my contextual group/tab/control rendered when web part page is displayed. However, if I add two of my custom web parts on the same page, I ran into error: ArgumentException: Item has already been added. Key in dictionary: 'Ribbon.MyContextualTabGroup' Key being added: 'Ribbon.MyContextualTabGroup'].</p>
  
  <p>How can I avoid this problem? What is the best approach? Ideally I would like the ribbon contextual group/tab/control render differently when different custom web part on the page is selected but I missed how that part works in SharePoint 2010 Ribbon framework.</p>
  
  <p>In an attempt to detect that the first web part on the page may have registered the contextual group, I tried SPRibbon.IsTabAvailable(tabID) but this always returns me true - even before I actually added the tab XML data extension. I am quite confused. Note I did not use the Custom Action/feature deployment approach but dynamically register ribbon data extension and page component.</p>
  
  <p>Below are code snippet showing how I added the ribbon:</p>
  
  <pre><code>
  
  Microsoft.Web.CommandUI.Ribbon ribbon = SPRibbon.GetCurrent(theWebPart.Page);
  if (ribbon != null)
  {
     // register data extension
     XmlDocument ribbonExtensions = new XmlDocument();
     ribbonExtensions.LoadXml(ContextualGroupInfo.ToXml());
     ribbon.RegisterDataExtension(ribbonExtensions.FirstChild, 
       "Ribbon.ContextualTabs._children");
  
     // Register initialize function
     var manager = new SPRibbonScriptManager();
     var methodInfo = typeof(SPRibbonScriptManager).GetMethod(
        "RegisterInitializeFunction", 
        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  
     methodInfo.Invoke(manager, new object[]
        {
           webPart.Page,
           "InitPageComponent",
           "/_layouts/PageComponent.js",
           false,
           "RibbonCustomization.PageComponent.initialize()"
        });
  
     var commands = new List();
     commands.Add(new SPRibbonCommand(ContextualGroup.EnableContextualGroupCommand));
     commands.Add(new SPRibbonCommand(ContextualTab.EnableContextualTabCommand));
     ...
     // add ribbon button commands
     ...
  
     // initialize tab
     ribbon.Minimized = false;
     ribbon.CommandUIVisible = true;  
     if (!ribbon.IsTabAvailable(ContextualTab.ID))
     {
         ribbon.MakeTabAvailable(ContextualTab.ID);
         ribbon.EnableVisibilityContext(ContextualTab.VisibilityContext);
         ribbon.MakeContextualGroupInitiallyVisible(ContextualTabGroupID, string.Empty);
         ribbon.NormalizeContextualGroup(ContextualTabGroupID, string.Empty);
     }
  
     // Make the tab active by default when the page is opened.
     ribbon.InitialTabId = ContextualTab.ID;
     ...
  }
  </code></pre>