Dynamically populating SharePoint 2010 ribbon in different list views (Hack)

Hello, everyone!
Recently I had to think of a way how to show a custom “New A/B/C/…” button in the SharePoint’s ribbon bar in the group where standard “New item” and “New folder” are shown. Button should have different names, like “New server” or “New network”, depending on the view that user is in.

Views are pre-defined in schema and are filtered based on ContentType (List has ContentTypes such as “Server”, “Network”, etc.)

To cut a long story short – SharePoint 2010 ribbon is not elastic enough to let us inject new elements from code behind. So I ended up:
1) Creating whole pack of buttons in my feature (in Custom Actions element declaration)
2) Creating a web control that will hide (trim) all unnecessary buttons from ribbon at runtime (SharePoint 2010 ribbon allows that), based on the current Query of view where user is in
3) Putting that web control in the template view.aspx page in my solution
4) Re-designing list’s schema so that all views inherit from template view.apsx file

And now, to make a short story long, I’ll provide chunks of code samples from each step (this will be not a full code, but rather some important parts)

1) Buttons. Below I’ll add a declaration of one button. CommandUIDefinition is it’s markup definition and CommandUIHandler defines what happens when user clicks in that button, in my case – a new form of a particular content type will be opened. More information on ribbon definitions can be foundhere or here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version=“1.0” encoding=“utf-8”?>
<Elements xmlns=“http://schemas.microsoft.com/sharepoint/”>
  <CustomAction
   Id=“AddRibbonButtons”
   Location=“CommandUI.Ribbon.ListView”
   RegistrationId=“0x019DA4954B99CA4ABDBA03F299446906E4”
  RegistrationType=“ContentType”>
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location=“Ribbon.ListItem.New.Controls._children”>
          <Button Id=“ABC.Ribbon.NewItemAdditionalHardware”
          Command=“ABCAddNewAdditionalHardware”
          LabelText=“New Additional Hardware”
          Image16by16=“/_layouts/$Resources:core,Language;/images/formatmap16x16.png” Image16by16Top=“-176” Image16by16Left=“-64”
          Image32by32=“/_layouts/$Resources:core,Language;/images/formatmap32x32.png” Image32by32Top=“-320” Image32by32Left=“-64”
          TemplateAlias=“o2”
          Sequence=“0”
       />
        </CommandUIDefinition>
        …
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler Command=“ABCListAddNewAdditionalHardware”
                         CommandAction=“javascript:                        
             var options = {              
               url: ‘{SiteUrl}/Lists/ABC/NewForm.aspx?ContentTypeId=0x019DA4954B99CA4ABDBA03F299446906E4&amp;source=’ + SP.ListOperation.Selection.getSelectedList(),
               tite: ‘New Additional Hardware’,
               allowMaximize: false,
               showClose: true,
               dialogReturnValueCallback: function(dialogResult) { SP.UI.ModalDialog.RefreshPage(dialogResult); }
             };
            SP.UI.ModalDialog.showModalDialog(options);” />

         …
         </CommandUIHandlers>
      …
    </CommandUIExtension>

2) WebControl. This is where the magic happens (unnecessary button hiding, actually)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public partial class RibbonActivator : UserControl
{
    public string ContentTypeID = String.Empty;
        
    protected void Page_Load(object sender, EventArgs e)
    {
        ViewInfo? currentViewinfo = SPTools.GetCIsViewInfo(SPContext.Current.ViewContext.View);
        if (currentViewinfo != null)
            ContentTypeID = currentViewinfo.Value.ContentTypeID; //set content id variable which is used in aspx

        if (SPRibbon.GetCurrent(Page) == null)
        {
            return;
        }
        var ribbon = SPRibbon.GetCurrent(Page);  
        List<ViewInfo> allViewsInfo = SPTools.GetViewInfoArray();

        // hide all ribbon buttons except button for current content type id
        foreach (ViewInfo itemViewInfo in allViewsInfo)
        {
            if ((currentViewinfo == null) || (itemViewInfo.Key != currentViewinfo.Value.Key))
            {
                ribbon.TrimById(“ABC.Ribbon.NewItem” + itemViewInfo.Key); 
            }
        }

        if (currentViewinfo != null) // hide new item and new list item buttons, except when view is not related to a content type (e.g. allitems.aspx)
        {
            ribbon.TrimById(“Ribbon.ListItem.New.NewListItem”);
            ribbon.TrimById(“Ribbon.ListItem.New.NewFolder”);
        }
    }
}

SPTools is our little secret magical stash.

3) !!! Making a template for list’s view pages. This is an important step. inside the SharePoint Hive (14 folder) we have a TEMPLATE/Pages folder which has files that by default are used as “base” pages for list forms and list views. What I did was copy the contents of viewpage.aspx file (the one responsible for views) and copy it inside my custom aspx file in the Visual Studio solution. Then, I added the declaration of my web control inside that newly created “template” page. I have put the new page next to Schema.xml definition on the list. Here are the contents of the page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<%@ Page language=“C#” MasterPageFile=“~masterurl/default.master”    Inherits=“Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c”  %> 
<%@ Register Tagprefix=“SharePoint” Namespace=“Microsoft.SharePoint.WebControls” Assembly=“Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> 
<%@ Register Tagprefix=“Utilities” Namespace=“Microsoft.SharePoint.Utilities” Assembly=“Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> 
<%@ Import Namespace=“Microsoft.SharePoint” %> 
<%@ Assembly Name=“Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> 
<%@ Register Tagprefix=“WebPartPages” Namespace=“Microsoft.SharePoint.WebPartPages” Assembly=“Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=“ApplicationPages” Namespace=“Microsoft.SharePoint.ApplicationPages.WebControls” Assembly=“Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=“ABC” TagName=“RibbonActivator” Src=“~/_controltemplates/ABC/RibbonActivator.ascx” %>

<asp:Content ID=”Content1″ ContentPlaceHolderId=”PlaceHolderPageTitle” runat=”server”><SharePoint:ListProperty ID=”ListProperty1″ Property=”TitleOrFolder” runat=”server”/> – <SharePoint:ListProperty ID=”ListProperty2″ Property=”CurrentViewTitle” runat=”server”/></asp:Content>
<asp:Content ID=”Content2″ ContentPlaceHolderId=”PlaceHolderPageTitleInTitleArea” runat=”server”>
    <SharePoint:ListProperty ID=”ListProperty3″ Property=”TitleBreadcrumb” runat=”server”/>
    <SharePoint:UIVersionedContent ID=”UIVersionedContent1″ UIVersion=”4″ runat=”server”>
        <ContentTemplate>
            <span id=”Span1″ class=”ms-ltviewselectormenuheader” runat=”server”>
                <SharePoint:ListTitleViewSelectorMenu AlignToParent=”true” id=”LTViewSelectorMenu” runat=”server” />
            </span>
        </ContentTemplate>
    </SharePoint:UIVersionedContent>
</asp:Content>
<asp:content ID=”Content3″ contentplaceholderid=”PlaceHolderAdditionalPageHead” runat=”server”>
    <SharePoint:RssLink ID=”RssLink1″ runat=”server” />
</asp:content>
<asp:Content ID=”Content4″ ContentPlaceHolderId=”PlaceHolderPageImage” runat=”server”><SharePoint:ViewIcon Width=”145″ Height=”54″ runat=”server” /></asp:Content>
<asp:Content ID=”Content5″ ContentPlaceHolderId=”PlaceHolderLeftActions” runat=”server”>
<SharePoint:RecentChangesMenu runat=”server” id=”RecentChanges”/>
<SharePoint:ModifySettingsLink ID=”ModifySettingsLink1″ runat=”server” />
</asp:Content>
<asp:Content ID=”Content6″ ContentPlaceHolderId =”PlaceHolderBodyLeftBorder” runat=”server”>
 <div height=”100%” class=”ms-pagemargin”><img src=”/_layouts/images/blank.gif” width=’6′ height=’1′ alt=”” /></div>
</asp:Content>
<asp:Content ID=”Content7″ ContentPlaceHolderId=”PlaceHolderMain” runat=”server”>
        <WebPartPages:WebPartZone runat=”server” FrameType=”None” ID=”Main” Title=”loc:Main” />

        <!– customization –>
        <ABC:RibbonActivator runat=”server” />

</asp:Content>
<asp:Content ID=”Content8″ ContentPlaceHolderId=”PlaceHolderBodyAreaClass” runat=”server”>
<style type=”text/css”>
.ms-bodyareaframe {
    padding: 0px;
}
</style>
</asp:Content>
<asp:Content ID=”Content9″ ContentPlaceHolderId=”PlaceHolderPageDescription” runat=”server”>
<SharePoint:ListProperty ID=”ListProperty4″ CssClass=”ms-listdescription” Property=”Description” runat=”server”/>
</asp:Content>
<asp:Content ID=”Content10″ ContentPlaceHolderId=”PlaceHolderCalendarNavigator” runat=”server”>
  <SharePoint:SPCalendarNavigator id=”CalendarNavigatorId” runat=”server”/>
  <ApplicationPages:CalendarAggregationPanel id=”AggregationPanel” runat=”server”/>
</asp:Content>

4) Binding new “template” page to list views. Here I’ll demonstrate how to associate custom viewpage “template” with the list views. This is done inside the list Schema.xml definition.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<Views>
    …
      <!–Server–>
      <View BaseViewID=“15” Type=“HTML” WebPartZoneID=“Main” DisplayName=“$Resources:ABC.External,vwServer” MobileView=“TRUE” SetupPath=“features\$SharePoint.Feature.DeploymentPath$\ABC\viewpage.aspx” ImageUrl=“/_layouts/images/generic.png” Url=“Server.aspx”>
        <Toolbar Type=“Standard” />
        <XslLink Default=“TRUE”>main.xsl</XslLink>
        <RowLimit Paged=“TRUE”>30</RowLimit>
        <ViewFields>
          <FieldRef Name=“Attachments”></FieldRef>
          <FieldRef Name=“ABCID”></FieldRef>
          <FieldRef Name=“LinkTitle”></FieldRef>
          <FieldRef Name=“Servicing”></FieldRef>
          <FieldRef Name=“Supporting”></FieldRef>
        </ViewFields>
        <Query>
          <Where>
            <Eq>
              <FieldRef Name=‘ContentType’ />
              <Value Type=‘Computed’>$Resources:ABC.External,CTServer</Value>
            </Eq>
          </Where>
          <OrderBy>
            <FieldRef Name=“ID”></FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name=“NoAnnouncements” Location=“Resource(wss,noXinviewofY_LIST)” />
          <ParameterBinding Name=“NoAnnouncementsHowTo” Location=“Resource(wss,noXinviewofY_DEFAULT)” />
        </ParameterBindings>
      </View>
   …
</Views>

And, that’s pretty much it, now we’ll have different buttons in different views for your list  🙂
Hope this was helpful for someone, take care!

Leave a Reply

Your email address will not be published. Required fields are marked *