Friday, October 22, 2010

XsltListViewWebPart – how to hide the ribbon

A reader of my blog asked me this in a comment to one of the previous postings and I had also wondered about it myself on several occasions. The thing is that sometimes you may not want the ribbon to appear when you select (clicking on the web part basically selects it) the XLV web part or select some of the items that the web part displays. The solution to this one turned out to be pretty simple and straight-forward – it involves creating a small custom XSLT file which does the trick with several lines of javascript (the selection of the web part and the displaying/hiding of the ribbon are all implemented with javascript in standard SharePoint 2010, so it is pretty logical to counter this also with javascript). The replacing of the standard “main.xsl” in the XslLink property of the web part and the setting of one additional property of its hidden SPView are then the only thing left that you need to fulfill the task (I’ll come to that in a moment).

So let me first shortly explain which are the javascript “culprits” that cause the page to display the “list” context specific ribbon when you click on the web part (not on a particular item – that’s a different case) or check the web part’s selection checkbox at the top right corner. If you inspect closely the HTML of the page containing the XLV web part you will be able to find these two HTML elements:

<td id="MSOZoneCell_WebPartWPQ2" valign="top" class="s4-wpcell" onkeyup="WpKeyUp(event)" onmouseup="WpClick(event)">

 

<input type="checkbox" id="SelectionCbxWebPartWPQ2" class="ms-WPHeaderCbxHidden" title="Select or deselect test Web Part" onblur="this.className='ms-WPHeaderCbxHidden'" onfocus="this.className='ms-WPHeaderCbxVisible'" onkeyup="WpCbxKeyHandler(event);" onmouseup="WpCbxSelect(event); return false;" onclick="TrapMenuClick(event); return false;" />

The first one is one of the top container elements of the XLV web part – have a look at its “onmouseup” attribute – it is this javascript bit that triggers the selection of the web part and the appearing of the parent list’s contextual ribbon. The second element is the selection checkbox control itself. Notice the “id” attributes of these two HTML elements – they both have one and the same suffix – “WPQ2” – this is actually something like an web part index which in case you have more than one web parts on the page can be used to identify these two elements for a specific web part.

And let’s go directly to the custom XSLT that hides the ribbon when used in the XLV web part:

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">

  <!-- import the standard main.xsl so that we have all standard stuff -->

  <xsl:import href="/_layouts/xsl/main.xsl"/>

  <!-- this template was copied from the standard vwstyles.xsl -->

  <xsl:template match="/">

    <!-- only this javascript block was added -->

    <script>

      try

      {

        // remove the click handler of the containing element

        $get('MSOZoneCell_WebPart<xsl:value-of select="$WPQ"/>').onmouseup = function (){};

        // remove the TD element containing the wp selection checkbox in the wp's header

        $get('SelectionCbxWebPart<xsl:value-of select="$WPQ"/>').parentNode.parentNode.style.display = 'none';

      }

      catch (ex) {}

    </script>

    <xsl:choose>

      <xsl:when test="$RenderCTXOnly='True'">

        <xsl:call-template name="CTXGeneration"/>

      </xsl:when>

      <xsl:when test="($ManualRefresh = 'True')">

        <xsl:call-template name="AjaxWrapper" />

      </xsl:when>

      <xsl:otherwise>

        <xsl:apply-templates mode="RootTemplate" select="$XmlDefinition"/>

      </xsl:otherwise>

    </xsl:choose>

  </xsl:template>

</xsl:stylesheet>

As you see, it is pretty concise and doesn’t need much explanation as to what it does and how it does it – I also put several comments inside it, so that you can get a better clue of its workings. Notice that the “WPQ” index that I mentioned above is actually available in an XSL parameter (with the same name) that the XLV web part has initialized for you, so the localizing of the two HTML elements in the javascript becomes a really easy task.

This snippet should be saved as a file in the TEMPLATE\LAYOUTS\XSL folder (I saved it as “main_noribbon.xsl”). After you have the XSL file you will need to set the XLV web part to use it – you have two options here – to set the XslLink property of the web part (the value in this case should be: /_layouts/xsl/main_noribbon.xsl) – you can do that easily using the SharePoint UI. The other option is to set the XslLink property of the associated hidden SPView of the web part (the value in this case is simply the name of the file: main_noribbon.xsl) – the standard UI can’t be used in this case, so you will need some lines of code here (see below).

And … you need one more thing to have it all working. Apart from the ability to select the whole web part, the XLV allows you to select individual item rows which also results in displaying the ribbon. To override this you won’t need extra XSL because the XLV web part provides this as an option out of the box – it is about the so called “view styles” that you can use for list views and hence XLV web parts. The view style can be changed easily from the standard UI – you click the “modify view” button in the ribbon (you have already disabled the ribbon? – no worries – you can do the same from the edit tool-pane of the XLV – it is the “Edit the current view” link there). In the standard “Edit View” page that will open you can scroll down and locate the “Style” section, expand it and then in the “View Styles” list box select the topmost option – “Basic Table”. This view style is pretty much the same as the “Default” one save the ability to select the item rows.

As you saw, you can apply the changes (once you have the XSL file in place) using the standard SharePoint UI alone. And here is how you can do it with code:

private static void XLVHideRibbon(SPWeb web, XsltListViewWebPart xlv)

{

    // if the page is in a library that requires check out, the file containing the XLV should be checked out before calling this method

 

    // get the hidden view of the XLV web part

    SPView hiddenView = web.Lists[new Guid(xlv.ListName)].Views[new Guid(xlv.ViewGuid)];

    // set its XslLink property to reference the custom "no ribbon" XSLT file

    hiddenView.XslLink = "main_noribbon.xsl";

 

    // web.ViewStyles[0] - Basic Table

    hiddenView.ApplyStyle(web.ViewStyles[0]);

    // update the hidden view

    hiddenView.Update();

}

Note that instead of setting the XslLink property of the XLV web part, I set the XslLink property of its hidden SPView, but this basically achieves the same effect.

12 comments:

  1. Hi Stefan,

    Hitesh here. Thank you so much for creating this post. I have implemented it and it is working fine, exactly the way I wanted.

    Regards
    Hitesh

    ReplyDelete
  2. Hi Stefan,

    actually, I have not see how to add a xlstlistview webpart by code in a visaul webpart code behind, then add properties... like .xsl . does this mean we can only add XLV in design view? something like<WebPartPages:XsltListViewWebPart ...

    ReplyDelete
  3. Hi Frank,
    If your question is how to add a XLV web part to a page with code, you can check this link http://www.sharepointoverflow.com/questions/6137/adding-xsltlistviewwebpart-on-page-context-menu-issue-in-folders-sp2010.
    The values of the properties are hard-coded in the sample, but you can modify them with the values you need in your case. Besides the ListId and ViewGuid properties, you can also set the Xsl or XslLink properties of the web part. Let me know if this is of help for you.

    ReplyDelete
  4. Tnx for sharing this Stefan, just what I needed :)

    ReplyDelete
  5. thanks for your sharing!

    However, I have a problem here: I have customized the XSLT template of List View Web Part; after insert your XSL main_noribbon.xsl into the webpart, my customization is removed.

    Do you have any suggestion? Thanks again!

    ReplyDelete
  6. Hi Anthony,
    I think the easiest way would be to do everything in SharePoint Designer 2010. So, first make your XSLT customizations there and the next step will be to make a small change in the Xsl property of the XLV web part. You can achieve this by switching from design to code view of the page containing the web part and then locating the code of the web part itself - most of it will be the XSLT contents of the "Xsl" property. Inside the XSL there should be an XSL import element: <xsl:include href="/_layouts/xsl/main.xsl"/> - just change the reference to "main.xsl" to "main_noribbon.xsl" and save the changes of the web part. Let me know if this works for you.
    Stefan

    ReplyDelete
  7. Hi,
    I have the same problem as Anthony.
    Follow your instruction above did not work too.

    ReplyDelete
  8. Hi Anonymous,
    When you make customizations with the SharePoint designer, the XSL modifications are saved in the "Xsl" property of the XLV web part. If you on the other hand set the "XslLink" property of the XLV web part to point to the custom XSLT file from the posting this will effectively override the stuff from the "Xsl" property - to get a better idea of the precedence of the "XslLink" and "Xsl" properties check this previous posting of mine - http://stefan-stanev-sharepoint-blog.blogspot.com/2010/08/xsltlistviewwebpart-several-xslt-tips.html; So if you want to keep your customizations working, you should not set the "XslLink" property of the web part - it needs to remain empty. Instead you will have to modify the contents of the "Xsl" property. The easiest way to do this is again in the SharePoint designer - just open the page containing the web part and switch to "code" view. Then locate the "Xsl" content of the XLV web part and replace the xsl:include element at the top to point to /_layouts/xsl/main_noribbon.xsl instead of to /_layouts/xsl/main.xsl
    Let me know if this solves your issue.
    Greets
    Stefan

    ReplyDelete
  9. Hi,
    thanks for your help. I could do one of your both tips...As I am newbee I did not know how to put your "private static void XLVHideRibbon" code...Could you help me by given to me a example of page name where to put it? (for example : AllItems.aspx...)
    Thanks

    ReplyDelete
  10. Hi Dan,
    I used this code from a console application. It needs to be run only once so normally you wouldn't need it on the view page. Here is a code snippet from a console application that calls it:
    using (SPSite site = new SPSite("http://devsp2010-eu1"))
    {
    SPWeb web = site.OpenWeb();
    SPFile file = web.GetFile("default.aspx");

    SPLimitedWebPartManager mngr = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
    // just take the first XLV web part
    XsltListViewWebPart xlv = mngr.WebParts.OfType<XsltListViewWebPart>().FirstOrDefault();
    if (xlv != null) XLVHideRibbon(web, xlv);
    }

    ReplyDelete
  11. Thank you, just what we needed. A little tip while working on the xsl file in _layouts/xsl/ is to remember to recycle the app-pool before testing if this works.

    ReplyDelete