Second Life of a Hungarian SharePoint Geek

July 25, 2011

Triggering an asynchronous refresh from code

In one of my former posts I’ve demonstrated how to modify the list item properties from an ECB custom action using the client object model.

You might have noticed there that after the modification I reloaded the list content by setting the page location to itself:

window.location.href = window.location.href;

It means that all of the page content is reloaded that may be not optimal given that SharePoint 2010 lists support asynchronous updating.

But how can we achieve this functionality from client side code? To understand that, we should first enable the manual refresh button in the web part properties.

(Note: Checking the ‘Show Manual Refresh Button’ checkbox will check the ‘Enable Asynchronous Update’ checkbox after applying the settings.)

image

Then let’s see what HTML code is injected as the result of this setting (most important part is highlighted with bold):

<a href=”javascript:” onclick=” javascript: __doPostBack(‘ctl00$m$g_e9bf1559_32e7_40ea_88fa_3aced214cc97$ctl02′,’cancel’);return false;”><img src=”/_layouts/images/staticrefresh.gif” id=”ManualRefresh” border=”0″ alt=”Click here to refresh the data view.” /></a>

In the code above the value ‘e9bf1559_32e7_40ea_88fa_3aced214cc97’ is the ID (Guid) of the list having the leading and trailing curly brackets trimmed and hyphens replaced with underscore.

We can reproduce that for the list displayed by the current page using a code like this:

  1. var selectedListId = SP.ListOperation.Selection.getSelectedList();
  2. var convertedListId = selectedListId.toLowerCase().replace(“-”, “_”).replace(“{“, “”).replace(“}”, “”);
  3. var controlId = ‘ctl00$m$g_’ + convertedListId + ‘$ctl02′;
  4. __doPostBack(controlId, ‘cancel’);

Note: The above solution works for my current SharePoint installation as long as at least the ‘Enable Asynchronous Update’ checkbox is checked at AJAX Options. There is no guarantee that the structure of the control ID remains the same in forthcoming cumulative updates / service packs, or if you add other web parts to the page.

The code relies on the client object model when determining the list ID by calling SP.ListOperation.Selection.getSelectedList(), so the sp.js file must be loaded before the script executes. See my former post about how to use ExecuteOrDelayUntilScriptLoaded to enforce that.

In my forthcoming post I will illustrate this technique via a complete example.

March 3, 2010

AJAX-enabling the TaxonomyWebTaggingControl

Filed under: AJAX, Reflection, SP 2010, Taxonomies — Tags: , , , — Peter Holpar @ 04:37

If you need to use the TaxonomyWebTaggingControl on a complex UI and would not like to refresh all the page if you have to change only the part where the taxonomy control is, you may try to use AJAX UpdatePanel as shown in the Visual Web Part code below.

  1. <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
  2. <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  3. <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  4. <%@ Register Tagprefix="Taxonomy" Namespace="Microsoft.SharePoint.Taxonomy" Assembly="Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  5. <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  6. <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
  7. <%@ Import Namespace="Microsoft.SharePoint" %>
  8. <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  9. <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart1UserControl.ascx.cs" Inherits="TestWebPart.VisualWebPart1.VisualWebPart1UserControl" %>
  10.  
  11. <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Always" RenderMode="Block" runat="server">
  12. <ContentTemplate>
  13. <Taxonomy:TaxonomyWebTaggingControl ID="TaxonomyControl" runat="server" />
  14.  
  15.  
  16. <p><asp:LinkButton ID="PostbackButton" OnClick="PostbackButton_OnClick" runat="server">Postback</asp:LinkButton></p>
  17.  
  18.  
  19. </ContentTemplate>
  20. </asp:UpdatePanel>

Of course, replace term store / group / set names to match your environment.

  1. using System;
  2. using System.Web.UI;
  3. using System.Web.UI.WebControls;
  4. using System.Web.UI.WebControls.WebParts;
  5. using Microsoft.SharePoint.Taxonomy;
  6. using Microsoft.SharePoint;
  7.  
  8. namespace TestWebPart.VisualWebPart1
  9. {
  10.     public partial class VisualWebPart1UserControl : UserControl
  11.     {
  12.         protected void Page_Load(object sender, EventArgs e)
  13.         {
  14.                 SPContext context = SPContext.Current;
  15.                 SPSite site = context.Site;
  16.                 TaxonomySession session = new TaxonomySession(site);
  17.                 TermStore termStore = session.TermStores["Metadata"];
  18.                 Group group = termStore.Groups["Test"];
  19.                 TermSet productsTermSet = group.TermSets["Products"];
  20.  
  21.                 TaxonomyControl.SspId.Add(termStore.Id);
  22.                 TaxonomyControl.TermSetId.Add(productsTermSet.Id);
  23.                 TaxonomyControl.IsAddTerms = true;
  24.                 TaxonomyControl.AllowFillIn = true;
  25.                 TaxonomyControl.IsMulti = true;
  26.         }
  27.  
  28.         protected void PostbackButton_OnClick(object sender, EventArgs e)
  29.         {
  30.             // do nothing
  31.         }
  32.     }
  33. }

On the first page load everything seems to be OK.

image

But when you click on the Postback button the taxonomy control seems to be lost as shown below.

image

To understand why it happens you should know that the TaxonomyWebTaggingControl is rendered on server side as a hidden field and a DIV element. Text field, icon added using client side scripts, as well other initialization steps required to the full functionality.

The client side script is produced by the private getOnloadJavascript method of the TaxonomyWebTaggingControl. To enable the taxonomy functionality, we should run first part of the script after the partial-page update. We can use the AJAX Sys.WebForms.PageRequestManager endRequest event to catch and inject our JavaScript to handle this requirement.

The code below shows you how to get the script we need using Reflection and register it on the page for re-initialization after the update happens.

  1. using System;
  2. using System.Web.UI;
  3. using System.Web.UI.WebControls;
  4. using System.Web.UI.WebControls.WebParts;
  5. using Microsoft.SharePoint.Taxonomy;
  6. using Microsoft.SharePoint;
  7. using Microsoft.SharePoint.Utilities;
  8. using System.Reflection;
  9. using System.Text;
  10.  
  11. namespace TestWebPart.VisualWebPart1
  12. {
  13.     public partial class VisualWebPart1UserControl : UserControl
  14.     {
  15.         protected void Page_Load(object sender, EventArgs e)
  16.         {
  17.                 SPContext context = SPContext.Current;
  18.                 SPSite site = context.Site;
  19.                 TaxonomySession session = new TaxonomySession(site);
  20.                 TermStore termStore = session.TermStores["Metadata"];
  21.                 Group group = termStore.Groups["Test"];
  22.                 TermSet productsTermSet = group.TermSets["Products"];
  23.  
  24.                 TaxonomyControl.SspId.Add(termStore.Id);
  25.                 TaxonomyControl.TermSetId.Add(productsTermSet.Id);
  26.                 TaxonomyControl.IsAddTerms = true;
  27.                 TaxonomyControl.AllowFillIn = true;
  28.                 TaxonomyControl.IsMulti = true;
  29.  
  30.                 // register the client script for taxonomy control initialization
  31.                 String key = "TaxonomyWebTaggingAjaxIncludeOnce";
  32.                 if (!this.Page.ClientScript.IsClientScriptBlockRegistered(base.GetType(), key))
  33.                 {
  34.  
  35.                     this.Page.ClientScript.RegisterClientScriptBlock(base.GetType(), key, GetReloadJavaScript(TaxonomyControl), true);
  36.                 }
  37.         }
  38.  
  39.         protected void PostbackButton_OnClick(object sender, EventArgs e)
  40.         {
  41.             // do nothing
  42.         }
  43.  
  44.         private string GetReloadJavaScript(TaxonomyWebTaggingControl taxonomyControl)
  45.         {
  46.             String script = String.Empty;
  47.  
  48.             String containerId = SPEncode.ScriptEncode(taxonomyControl.Controls[1].ClientID);
  49.  
  50.             Type type_TaxonomyWebTaggingControl = typeof(TaxonomyWebTaggingControl);
  51.  
  52.             MethodInfo mi_getOnloadJavascript = type_TaxonomyWebTaggingControl.GetMethod("getOnloadJavascript", BindingFlags.NonPublic | BindingFlags.Instance);
  53.             String fullScript = (String)mi_getOnloadJavascript.Invoke(taxonomyControl, null);
  54.             int pos = fullScript.IndexOf(String.Format("function {0}_load()", containerId));
  55.  
  56.             if (pos > -1)
  57.             {
  58.                 StringBuilder builder = new StringBuilder();
  59.                 builder.Append("var myPrm = Sys.WebForms.PageRequestManager.getInstance();");
  60.                 builder.Append("myPrm.add_endRequest(EndRequest);");
  61.                 builder.Append("function EndRequest(sender, args)");
  62.                 builder.Append("{");
  63.                 // we get te first part of the script needed to initialization
  64.                 // we start from pos 1, because we don't need the leading '{'
  65.                 builder.Append(fullScript.Substring(1, pos – 1));
  66.                 builder.Append("Microsoft.SharePoint.Taxonomy.ScriptForWebTaggingUI.onLoad('");
  67.                 builder.Append(containerId);
  68.                 builder.Append("');");
  69.                 builder.Append("}}");
  70.  
  71.                 script = builder.ToString();
  72.             }
  73.  
  74.             return script;
  75.         }
  76.     }
  77. }

Theme: Shocking Blue Green. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 42 other followers