Sorting Displays in Data View Web Parts

I figured out a great little trick for sorting a DVWP-based display based on a column name passed in the Query String.  You can see this in action in the default All Items or All Documents views in lists or libraries.  When you click on the column headers that allow sorting, the browser is sent to the same page with the Query String looking something like:

http://[servername]/Lists/[listname]Forms/AllItems.aspx?SortField=ContentType&SortDir=Asc

By passing the column name that you want to sort on in the Query String, the List View Web Part “knows” what to sort the display on and in what order.

If you want to build analogous functionality in a DVWP, you can easily rig the column headers to act the same way, but the trick is to get the items to then sort correctly.  In your body template, you need some XSL like the following:

<xsl:variable name="AscDesc">
 <xsl:choose>
  <xsl:when test="string-length($SortDir) = 0 or $SortDir = 'Asc'">ascending</xsl:when>
  <xsl:otherwise>descending</xsl:otherwise>
 </xsl:choose>  
</xsl:variable>
<xsl:for-each select="$Rows">
 <xsl:sort select="@*[name()=$SortField]" order="{$AscDesc}" />  
 <xsl:call-template name="Community_ContentDetailed.rowview">
  <xsl:with-param name="SiteType" select="$SiteType" /> 
  <xsl:with-param name="CommunityContentFilterValue" select="$CommunityContentFilterValue" /> 
 </xsl:call-template>
</xsl:for-each>

The cool line is #8.  It allows you to take the Query String value for SortField and use it as the column name by which to sort.  The select parameter in the xsl:sort evaluates to @ContentType (from the URL above).

I wanted to be able to easily add the sorting option to header columns in my DVWPs, so I created the following utility template to create the links.  It decides based on the Query String values whether this is the first or second click of the column header (ascending or descending) and shows the appropriate image indicator for the result.

 <xsl:template name="SortHeader">
  <xsl:param name="LinkText"/>
  <xsl:param name="ColumnName"/>
  <xsl:param name="SortField"/>
  <xsl:param name="SortDir"/>
  <xsl:variable name="ASortIMG" select="'/_layouts/images/sortaz.gif'"/>
  <xsl:variable name="DSortIMG" select="'/_layouts/images/sortza.gif'"/>
  <xsl:variable name="SortableIMG" select="'/SiteCollectionImages/sortable.gif'"/>
  <xsl:variable name="AscDesc">
   <xsl:choose>
    <xsl:when test="$ColumnName = $SortField and (string-length($SortDir) = 0 or $SortDir = 'Asc')">Desc</xsl:when>
    <xsl:otherwise>Asc</xsl:otherwise>
   </xsl:choose>
  </xsl:variable>
  <img alt="Sortable" border="0" src="{$SortableIMG}"/>
  <a href="#">
   <xsl:attribute name="onclick">
    document.location = '<xsl:value-of select="$URL"/>' +
     '?SortField=' + '<xsl:value-of select="$ColumnName"/>' +
     '&amp;SortDir=' + '<xsl:value-of select="$AscDesc"/>';
   </xsl:attribute>
   <xsl:value-of select="$LinkText"/>
   <span style="padding-left:2px;">
   <xsl:choose>
    <xsl:when test="$ColumnName = $SortField and ($SortDir = '' or $SortDir = 'Asc')">
     <img alt="Ascending - Click to Reverse" border="0" src="{$ASortIMG}"/>
    </xsl:when>
    <xsl:when test="$ColumnName = $SortField and $SortDir = 'Desc'">
     <img alt="Descending - Click to Reverse" border="0" src="{$DSortIMG}"/>
    </xsl:when>
    <xsl:otherwise>
    </xsl:otherwise>
   </xsl:choose>
   </span>
  </a>
 </xsl:template>

18 Comments

  1. Hi,

    I’ve got 3 form web parts for providing 3 parameters (number) for displaying results in data view web part.
    Problem is DVWP displays no results without inserting parameters in 3 form web parts. What I want is to set the default value of all parameters from 0 to ‘show all’
    I think this is set in SELECTCOMMAND code :

    {SearchValue1}

    {SearchValue2}

    {SearchValue3}

    Please help me edit the code, so DVWP by default wil show all results from document library, and by inserting the value to text box (form web part) will narrow the results.

    tnx

    Klemen

    Reply
    • Klemen:

      It’s a little difficult for me to figure out what you’re trying to do. Can you send me the code for your DVWP (marc dot anderson at sympraxisconsulting dot com)? I’d be happy to take a look.

      M.

      Reply
  2. Marc,

    I think this is exactly what I need. I have been struggling with the built-in sorting and its built-in problems. (e.g. sorting numbers and sorting user names enter via the people picker). It looks like this will give me what I need to take control.

    Also, since I have some pages that are a combination of connected DVWP this will help. I am now able to pass filtering info back in &source= from the new and edit pages so that the user does not loose their place and the page does not reset, but this will allow me to also pass back sort info as well which will be nice.

    I have been playing with the above for about an hour in a test DVWP but I am unsure where all the pieces go. I am still really new to XSL. Do you have an example in any of your blogs that shows all of the above the code in place within a DVWP?

    Thanks,
    Steve

    Reply
    • Steve:

      I don’t think I have a whole DVWP I can point you to. I think I have the actual pages where I used this stored away, but I won’t be able to find them without some work. Do you have some specific questions I can help with?

      M.

      Reply
  3. Hi Marc,

    I was confused about the .

    I took some time yesterday and brought the DVWP into an editor where I could reformat it and see what is really going on. I replaced out your custom call to the built in row view stuff.

    Right now I have it working with 1 problem. I tried to add another parameter and a decision structure to fix the sorting problems with text vs. number that seems to be inherent to Sharepoint.

    I now have the code below but it always goes to the otherwise statement. I suspect that I have a problem with my param either not being set or the wrong value but I am not sure how to debug it.

    I didn’t care for decalring the for-each 2x but the XSL was not happy when I tried to use a param right in the sorting tag with data-type=”{$SortType}”.

    Have you tried something like this before or is there a better way to adjust the sorting type.

    If this is the best way do you know what I might be doing wrong or can you tach me to fish and let me know how debug works in XSL/SPD?

    Thanks!

    [Standard for-each stuff here…]

    [Standard for-each stuff here…]

    Reply
    • I’m happy to teach you how to fish! Unfortunately, code doesn’t come through on comments. Can you send me what you want me to look at using the Contact link above?

      M.

      Reply
  4. Hi I have a couple of quick questions for you about your post.

    I am trying to get the code that you have provided to work in my dataview web part.

    What is SiteType and CommunityContentFilterValue

    I am assuming that the code u are using will replace the .rowview template I have

    I have got it to the point of being able to click, but the sort does not happen.

    Can you provide some insight…

    Reply
    • Chris:

      SiteType and CommunityContentFilterValue were two columns in my list which I needed to pass into my rowview template for other reasons. The first chunk of code above went inside the body template, and the second was a template of its own.

      Keep in mind that your templates can be named anything. I tend to keep the .body and .rowview postfixes for clarity, but you can name them anything.

      M.

      Reply
  5. I’m trying to get this working within my XSL, but it keeps kicking out an error when I add this line to my foreach statement:

    am I missing something?

    Reply
  6. Hi Marc,
    I had created DVWP to get details from Two Lists, everything is working fine..
    i want to add Sorting on column header. as u told to ‘Garima’ i mention the code at the bottom and before tag. sorting is not working.
    how can i achive this. functionallity.
    Nvz.

    Reply

Leave a Reply