{"id":268,"date":"2010-07-31T13:49:54","date_gmt":"2010-07-31T21:49:54","guid":{"rendered":"http:\/\/singchan.com\/?p=268"},"modified":"2011-10-11T14:08:26","modified_gmt":"2011-10-11T22:08:26","slug":"sharepoint-2010-fixing-the-msdn-contextual-tab-web-part-walkthrough","status":"publish","type":"post","link":"https:\/\/singchan.com\/wordpress\/2010\/07\/31\/sharepoint-2010-fixing-the-msdn-contextual-tab-web-part-walkthrough\/","title":{"rendered":"SharePoint 2010: Fixing the MSDN Contextual Tab Web Part Walkthrough"},"content":{"rendered":"<blockquote><p><strong>UPDATE!!!<\/strong><\/p>\n<p>The latest versions of the CKSDev for SharePoint 2010 include an SPI for stubbing out a contextual web part! I highly recommend that anyone coding for SP2010 to install the CKS Dev Tools!<\/p>\n<p><a href=\"http:\/\/cksdev.codeplex.com\/\" title=\"CKS: Development Tools Editon\" target=\"_blank\">http:\/\/cksdev.codeplex.com\/<\/a><\/p><\/blockquote>\n<p>I haven&#8217;t had much opportunity to work with SharePoint 2010 in the past few months. However, I did get to try out the MSDN walkthrough for creating a custom web part with contextual ribbon tab recently. You can find the article here: <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ff407578.aspx\" target=\"_blank\">http:\/\/msdn.microsoft.com\/en-us\/library\/ff407578.aspx<\/a><\/p>\n<p>In a nutshell, what&#8217;s supposed to happen is when you click on the web part, there will be a custom tab that appears in the Ribbon. It all works great for the first instance of the custom web part you place onto a page, but if you try adding a second instance of the web part, your page blows up!<\/p>\n<p>You&#8217;ll get the following error:<br \/>\n<em>Item has already been added. Key in dictionary: &#8216;Ribbon.CustomContextualTabGroup&#8217;  Key being added: &#8216;Ribbon.CustomContextualTabGroup&#8217;<\/em><\/p>\n<p>:-\/ &#8230; looks like there wasn&#8217;t much QA done for the walkthrough. Anyways, to make a short story shorter&#8230; I posted a question on the <a href=\"http:\/\/social.technet.microsoft.com\/Forums\/en-US\/sharepoint2010programming\/thread\/8604fda5-dad3-49e5-b820-af98ae2fb3cf\" target=\"_blank\">TechNet forums<\/a> and Dallas Tester from MS did get back to me with a bunch of suggestions.<\/p>\n<p>Here are the changes you can make to allow for multiple instances of the custom web part to appear on the page without everything blowing up.<\/p>\n<p><strong>Make the following modifications to the ContextualTabWebPart class.<\/strong><\/p>\n<p>Add the global &#8216;_added&#8217; bool and OnInit event handler:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">static bool _added = false;\r\n\r\nprotected override void OnInit(EventArgs e)\r\n{\r\n base.OnInit(e);\r\n _added = false;\r\n}<\/pre>\n<p>Since we no longer have to get the unique component ID in the delay script, I changed DelayScript into a private string:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">private string delayScript = @&quot;\r\n function _addCustomPageComponent()\r\n {\r\n  for (var i = 0; i &lt; g_customWebPartIds.length; i++)\r\n  {\r\n    SP.Ribbon.PageManager.get_instance().addPageComponent(new ContextualTabWebPart.CustomPageComponent(g_customWebPartIds&#x5B;i]));\r\n  }\r\n }\r\n\r\n function _registerCustomPageComponent()\r\n {\r\n  SP.SOD.registerSod(&quot;&quot;CustomContextualTabPageComponent.js&quot;&quot;, &quot;&quot;\/_layouts\/CustomContextualTabPageComponent.js&quot;&quot;);\r\n  var isDefined = &quot;&quot;undefined&quot;&quot;;\r\n  try\r\n  {\r\n   isDefined = typeof(ContextualTabWebPart.CustomPageComponent);\r\n  }\r\n  catch(e)\r\n  {\r\n  }\r\n  EnsureScript(&quot;&quot;CustomContextualTabPageComponent.js&quot;&quot;,isDefined, _addCustomPageComponent);\r\n }\r\n SP.SOD.executeOrDelayUntilScriptLoaded(_registerCustomPageComponent, &quot;&quot;sp.ribbon.js&quot;&quot;);&quot;;<\/pre>\n<p>Modify the OnPreRender event handler:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">protected override void OnPreRender(EventArgs e)\r\n{\r\n base.OnPreRender(e);\r\n\r\n ClientScriptManager csm = this.Page.ClientScript;\r\n string componentId = SPRibbon.GetWebPartPageComponentId(this); \/\/ the unique component id \r\n\r\n \/\/ if this is the first instance of the custom web part,\r\n \/\/we need to add the contextual tab to the ribbon\r\n if (!_added)\r\n {\r\n  this.AddContextualTab();\r\n  _added = true;\r\n }\r\n\r\n \/\/ we need to create an array which will store the IDs of all instances of our custom web part\r\n csm.RegisterClientScriptBlock(\r\n  this.GetType(), &quot;DeclareCustomWebPartArray&quot;, &quot;var g_customWebPartIds = new Array();&quot;, true);\r\n\r\n \/\/ add this webpart's ID to our array\r\n csm.RegisterClientScriptBlock(\r\n  this.GetType(), &quot;AddCustomWebPartId&quot; + componentId, &quot;g_customWebPartIds.push('&quot; + componentId + &quot;');&quot;, true);\r\n   \r\n csm.RegisterClientScriptBlock(this.GetType(), &quot;ContextualTabWebPart&quot;, this.delayScript, true);\r\n}<\/pre>\n<p><strong>If you want to verify that the correct web part is trigger the Ribbon commands, you can modify the &#8216;<em>handleCommand<\/em>&#8216; method in &#8216;<em>CustomContextualTabPageComponent.js<\/em>&#8216;<\/strong><\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">handleCommand: function ContextualTabWebPart_CustomPageComponent$handleCommand(commandId, properties, sequence) {\r\n if (commandId === 'CustomContextualTab.HelloWorldCommand') {\r\n  alert(this._webPartPageComponentId + ' says: Hello, world!');\r\n }\r\n if (commandId === 'CustomContextualTab.GoodbyeWorldCommand') {\r\n  alert(this._webPartPageComponentId + ' says: Good-bye, world!');\r\n }\r\n}<\/pre>\n<p>Here&#8217;s a <a href=\"https:\/\/singchan.com\/wordpress\/wp-content\/uploads\/2010\/07\/ContextualTabWebPart.zip\">ZIP file of the entire solution<\/a> in case you&#8217;re too lazy to make the modifications yourself. \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>UPDATE!!! The latest versions of the CKSDev for SharePoint 2010 include an SPI for stubbing out a contextual web part! I highly recommend that anyone coding for SP2010 to install the CKS Dev Tools! http:\/\/cksdev.codeplex.com\/ I haven&#8217;t had much opportunity to work with SharePoint 2010 in the past few months. However, I did get to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,134,43,135],"tags":[44,136,58,138,139,164,91,49,42,47,46,137],"class_list":["post-268","post","type-post","status-publish","format-standard","hentry","category-javascript","category-ribbon-sharepoint-development","category-sharepoint-development","category-web-part","tag-44","tag-contextual-tab","tag-custom","tag-error","tag-fix","tag-javascript","tag-js","tag-ribbon","tag-sharepoint","tag-ue","tag-user-experience","tag-web-part-2"],"_links":{"self":[{"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/posts\/268","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/comments?post=268"}],"version-history":[{"count":16,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/posts\/268\/revisions"}],"predecessor-version":[{"id":306,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/posts\/268\/revisions\/306"}],"wp:attachment":[{"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/media?parent=268"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/categories?post=268"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/singchan.com\/wordpress\/wp-json\/wp\/v2\/tags?post=268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}<!-- WP Super Cache is installed but broken. The constant WPCACHEHOME must be set in the file wp-config.php and point at the WP Super Cache plugin directory. -->