Save Sitecore Item from .aspx editor

Sitecore is an extendable platform, no doubt about it. For example it allows you to add an external (.aspx) page, to an item:

Advanced Sitecore Google Maps Editor

Advanced Sitecore Google Maps Editor

The page will then show up on your item. But what if you wish to modify the actual Sitecore item from the page? Like in this case:
This is one of the editors for the new Advanced Sitecore Google Maps (WCAG Edition) module. The page allows a user to apply a Google Maps map to a Sitecore item. When the user press “Save map”, the map center and zoom-level is saved to the Sitecore item:

Save map center and zoom to the current Sitecore item

Save map center and zoom to the current Sitecore item

This can only be achieved by hooking into some of Sitecore’s Javascript classes. When the “Save map” button is pressed I hook into the window.parent.scForm Javascript object and call item:load and item:refreshchildren.

All of this can be achieved from code-behind. On the button’s On_Click event I modify the current Sitecore item, and then use RegisterStartupScript to register the Javascript events:

protected void btnSave_Click(object sender, EventArgs e)
{
  // Get the Sitecore item to store map center and zoom level
  Sitecore.Data.Database db = Sitecore.Configuration.Factory.GetDatabase(Request.QueryString["database"]);
  Item item = db.GetItem(Request.QueryString["id"]);
  item.Fields["zoom"] = myZoomLevel;
  item.Fields["center"] = myCenter;
  // Now register the client startup script to be executed
  // When page posts back to save the modified Sitecore item
  SitecoreHelper.RegisterRefreshScript(Page, Request.QueryString["id"]);
}

The final function, SitecoreHelper.RegisterRefreshScript, is my own helper function that will register the startup script:

public static void RegisterRefreshScript(Page page, string id)
{
  StringBuilder message = new StringBuilder();
  message.Append("var parentScForm = window.parent.scForm;" + Environment.NewLine);
  message.Append(string.Format("parentScForm.postRequest('','','','item:load(id={0})');", id) + Environment.NewLine);
  message.Append(string.Format("parentScForm.postRequest('','','','item:refreshchildren(id={0})');", id) + Environment.NewLine);
  if (!page.ClientScript.IsStartupScriptRegistered("RefreshItem"))
  {
    page.ClientScript.RegisterStartupScript(typeof(string), "RefreshItem", message.ToString(), true);
  }
}

Thanks to the Sitecore support team to help me out with this one. BTW: It works with both Sitecore 5 and Sitecore 6.

Adding nbsp to asp:DropDownList title

I was trying to mimmick a tree-list in a drop down box. As wee all know, simpler is better, so I just added a few  ’s in front of my title before adding the ListItem to the DropDownList:

ListItem listItem = new ListItem("  " + Item.Title, item.ID.ToString());
ddCategory.Items.Add(listItem);

But because the ListItem is clever enough to encode the contents of the title field, all I get is:

Added   in drop down failed

Added in drop down failed

How can I overcome this? Simply by using Server.HtmlDecode(). Here is a small function that returns a string of HtmlDecoded  ’s that can be used in the dropdown:

private string Prefix(int count)
{
  if (count == 0)
    return "";
  StringBuilder sb = new StringBuilder();
  for (int i=0;i<count;i++)
  {
    sb.Append("&nbsp;");
  }
  return Server.HtmlDecode( sb.ToString() );
}

Now I can add the spaces to my ListItem:

ListItem listItem = new ListItem(Prefix(level*4) + item.Title, item.ID.ToString());
ddCategory.Items.Add(listItem);

An the dropdown is a simple treelist:

Drop down with tree-like structure

Drop down with tree-like structure

Automatically create TabIndex in a repeater

In order to conform with the Section 508 Accessibility guidelines, and the WCAG Guidelines, you must provide a tabindex for all of your buttons, checkboxes etc.
So what should you do if you create these elements within a Repeater List Control? Then you don’t know how many buttons, checkboxes etc. you have.

The solution is to create a code-behind property (or function) and then call it using the <%# … %> syntax. Please observe the following example:

<asp:Repeater ID="repGroups" runat="server">
  <HeaderTemplate>
   
<ul>
  </HeaderTemplate>
  <ItemTemplate>
   
	<li>     
     
<div>
        <asp:CheckBox ID="cbGroup" Checked="true" runat="server"
         TabIndex='<%# TabIndex %>' Text='<%# Eval("Title") %>' />
     </div>
   </li>
  </ItemTemplate>
  <FooterTemplate>
   </ul>
  </FooterTemplate>
</asp:Repeater>

Notice that asp:CheckBox uses the TabIndex=’<%# TabIndex %>’ to call a property on the page’s codebehind file. This property simply increases an integer and returns the new value:

private int _tabIndex = 0;

public int TabIndex
{
  get
  {
    _tabIndex++;
    return _tabIndex;
  }
}

The private variable _tabIndex is reset each time the page is called, and the TabIndex property returns a new value each time it is called, giving you tabindexes from 1 to infinite.