Friday, March 09, 2007

Tutorial: Making use of Ribbons and Galleries

This post applies to Sitecore 5.3

What really rocks when it comes to Sitecore 5.3 is a lot, but one of the greatest user features must surely be Ribbons, and especially the Galleries (well, at least in my opinion) and so, that's what i'm gonna cover in this post.

Galleries are, in sitecore, XAML / Sheer UI controls that enable you to have a lot more flexible content in the menu than traditional menus would allow. They're based on the <gallery> control with the base of GalleryForm and are easy enough to create - the real trick is to know when you want to have a gallery and when a button/combo button is more appropriate.

The relations between ribbons, chunks & strips can be awkward at a first look, but they're really not chaotic at all..

  • Ribbons contain Strips
  • Strips contain Chunks
  • Chunks contain, well, whatever you want..
Easiest way to go about making our own are to go through the list in reverse and create a Chunk, then a Strip and then add the Strip to a Ribbon.

Theoretically you could add whatever you want to the Chunk, but button-wise the commonly used ones are:

  • Large Button
  • Large Combo Button
  • Large Gallery Button
  • Small Button
  • Small Combo Button
  • Small Gallery Button
and actually, you can break it down even further since Large and Small are just variations of the same buttons but appear different, so what we're left with is:

  • Button
  • Combo Button
  • Gallery Button

For this tutorial let's use a scenario where we want to have easy access to a userlist that would enable us to have a fast way to toggle a users write permission on the current item.



So, the approach to creating this gallery is the same as when creating any sitecore control, and that is:

  1. create the layout
  2. create the code
  3. hook it up to sitecore
and, specifically for this gallery that means:
  1. create the xml layout of the control
  2. create the necessary codebeside for it
  3. assign it to a gallery button

Step 1: code of the Gallery.ToggleAccess xml layout:

<?xml version="1.0" encoding="utf-8" ?> <control
xmlns:def="Definition"
xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense"
xmlns:shell="http://www.sitecore.net/shell">
<Gallery.ToggleAccess>
<Gallery>
<CodeBeside
Type="Interfolio.ToggleAccess.ToggleAccessGalleryForm,Interfolio.ToggleAccess"/> <input type="hidden" id="reloadOnShow" value="1" />
<DataContext ID="EntityDataContext" DataViewName="Domain"
DefaultItem="/" Root="/sitecore/users"/>
<GridPanel
Width="100%" Height="100%">
<MenuHeader
Header="Users"/>
<Scrollbox Height="100%" Padding="0px"
Border="none" Background="transparent" GridPanel.Height="100%">
<DataTreeview ID="EntityTreeview" Width="100%"
DataContext="EntityDataContext" Root="false" AllowDragging="false"
DblClick="ToggleAccess"/>
</Scrollbox>
<Gallery.Grip/>
</GridPanel>
</Gallery>
</Gallery.ToggleAccess>
</control>

Step 2: code for the ToggleAccessGalleryForm C# class:

namespace Interfolio.ToggleAccess
{
public class ToggleAccessGalleryForm :
GalleryForm
{
protected DataContext EntityDataContext;
protected
DataTreeview EntityTreeview;
public
ToggleAccessGalleryForm()
{
}
private static ID
GetCurrentEntityID()
{
string text1 = StringUtil.GetString(new string[] {
WebUtil.GetQueryString("en") });
if (ID.IsID(text1))
{
return
ID.Parse(text1);
}
return ID.Null;
}
private static string
GetEntityName(Domain domain, ID entityID)
{
if (entityID ==
ItemIDs.AnonymousUser)
{
return "anonymous";
}
UserItem ui =
domain.GetUser(entityID);
if (ui != null)
{
return
ui.DisplayName;
}
return Translate.Text("[unknown]");
}
private
static string GetIcon(Domain domain, ID entityID)
{
UserItem ui =
domain.GetUser(entityID);
if (ui != null)
{
return
ui.Icon;
}
RoleItem ri = domain.GetRole(entityID);
if (ri !=
null)
{
return ri.Icon;
}
return
"People/24x24/user1.png";
}
protected override void OnLoad(EventArgs
e)
{
base.OnLoad(e);
if (!Context.ClientPage.IsEvent)
{
string
querydomain =
Sitecore.StringUtil.GetString(WebUtil.GetQueryString("do"),"sitecore");
Domain
domain = Factory.GetDomain(querydomain);
this.EntityDataContext.Parameters =
"domain=" + domain.Name;
string folder = WebUtil.GetQueryString("en");
if
(!string.IsNullOrEmpty(folder))
{
this.EntityDataContext.Folder =
folder;
}
}
}
protected void ToggleAccess()
{
UserItem ui =
Sitecore.Context.Domain.GetUser(this.EntityTreeview.GetSelectionItem().ID);
Error.AssertNotNull(ui,
"failed to initialize user item");
Item itm =
Sitecore.Context.ContentDatabase.GetItem(WebUtil.GetQueryString("id"));
Error.AssertNotNull(itm,
"failed to initialize content item");
if (ui != null && itm !=
null)
{
using (new SecuritySwitcher(ui))
{
if
(itm.Access.CanWrite())
{
using (new
SecurityDisabler())
{
itm.Editing.BeginEdit();
itm.SecurityField.SetRights(ui,
ItemRights.DenyWrite);
itm.Editing.EndEdit();
Sitecore.Context.ClientPage.ClientResponse.Alert("Denied
write to " + itm.Name + " for " + ui.Name);
}
}
else
{
using (new
SecurityDisabler())
{
itm.Editing.BeginEdit();
itm.SecurityField.SetRights(ui,
ItemRights.AllowWrite);
itm.Editing.EndEdit();
Sitecore.Context.ClientPage.ClientResponse.Alert("Allowed
write to " + itm.Name + " for " + ui.Name);
}
}
}
}
}
}
}
Now that that's all taken care of, all that's left is to make sure the control can be found, and then create a gallery button in a chunk in a strip in a ribbon (see, not that hard to understand) and then finally assign the gallery control to the gallery button.

Step 3: Adding the button and wrapping up
  • Add the location of the control to the <controlsources> section in the web.config file and save it.
  • Go into Sitecore and switch to Core DB
  • Navigate to the Ribbons content (/sitecore/system/ribbons)
  • Create a Large/Small Gallery Button somewhere in a chunk
  • Set the properties of the button and finally set the Gallery field to the name of the gallery control, in this case Gallery.ToggleAccess
  • Save

Now your new gallery button will be in the chunk where you placed it, and clicking it will launch the gallery and you can go out the door, realize it's friday and have a well-deserved, cold pint of lager.

Take care,

P.

2 comments:

Anonymous said...

Wow! Peter. This is really awesome; would you mind allowing us making an article on the developer network based on this article? Naturally with appropiate credentials.

Unknown said...

Hey Lars!

Of course you can, i wouldn't have been able to write the post in the first place without you guys :)

P.