27 January 2010

I Need To… XSLT Modification for Sorting by Title

Recently a co-worker contacted me about changing the XSLT in the I need to… web part so that items in the drop down are sorted by Title instead of the default, which appears to be ID. Here’s the working response I was able to provide back to him:

There is a sorting command available in xslt. It has to be placed within the XSLT area of the web-part, but you’ll have to make it XML Safe. Here’s the line to add:

      <xsl:sort select="@Title"/>

I’ve modified the webpart file you sent to include this line. Here’s the text of the file with the changes highlighted:

<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name="Microsoft.SharePoint.Portal.WebControls.TasksAndToolsWebPart, Microsoft.SharePoint.Portal, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Height" type="string" />
        <property name="HelpMode" type="helpmode">Modeless</property>
        <property name="ChromeType" type="chrometype">Default</property>
        <property name="PageSize" type="int">-1</property>
        <property name="Description" type="string">Displays tasks and tools from a list</property>
        <property name="DataSourceID" type="string" />
        <property name="MissingAssembly" type="string">Cannot import this Web Part.</property>
        <property name="ShowWithSampleData" type="bool">False</property>
        <property name="AllowConnect" type="bool">True</property>
        <property name="Xsl" type="string">
                                    &lt;xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                                    version="1.0" exclude-result-prefixes="xsl ddwrt slwrt msxsl" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:slwrt="http://schemas.microsoft.com/WebParts/v3/SummaryLink/runtime"
                                        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:tnt="urn:schemas-microsoft-com:sharepoint:TasksAndToolsWebPart" &gt;
                                        &lt;xsl:param name="tasksAndtools_IsRTL" /&gt;
                                        &lt;xsl:param name="tasksAndTools_Width" /&gt;
                                        &lt;xsl:template match="/"&gt;
                                            &lt;xsl:call-template name="MainTemplate"/&gt;
                                        &lt;/xsl:template&gt;
                                        &lt;xsl:template name="MainTemplate" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"&gt;
                                            &lt;xsl:variable name="Rows" select="/dsQueryResponse/NewDataSet/Row"/&gt;
                                            &lt;xsl:variable name="RowCount" select="count($Rows)"/&gt;
                                            &lt;table border="0" cellpadding="0" cellspacing="0" style="border-collapse:collapse; margin:0px;"&gt;
                                                &lt;tr style="margin-top:3px;margin-bottom:1px;height:28px;border:0px;"&gt;
                                                    &lt;td style="padding-left:4px; white-space:nowrap ;"&gt;
                                                        &lt;xsl:if test="string-length($tasksAndTools_Width) != 0"&gt;                                                        
                                                            &lt;select id="TasksAndToolsDDID" class="ms-selwidth" style="width:{$tasksAndTools_Width}" size="1" title="Choose a task that you need to perform" &gt;
                                                            &lt;option selected="true" value="0"&gt;Select Organization&lt;/option&gt;
                                                            &lt;xsl:call-template name="MainTemplate.body"&gt;
                                                                &lt;xsl:with-param name="Rows" select="$Rows"/&gt;
                                                            &lt;/xsl:call-template&gt;
                                                        &lt;/select&gt;
                                                        &lt;/xsl:if&gt;
                                                        &lt;xsl:if test="string-length($tasksAndTools_Width) = 0"&gt;
                                                        &lt;select id="TasksAndToolsDDID" class="ms-selwidth" size="1" title="Choose a task that you need to perform"&gt;
                                                            &lt;option selected="true" value="0"&gt;Select Organization&lt;/option&gt;
                                                            &lt;xsl:call-template name="MainTemplate.body"&gt;
                                                                &lt;xsl:with-param name="Rows" select="$Rows"/&gt;
                                                            &lt;/xsl:call-template&gt;
                                                        &lt;/select&gt;
                                                        &lt;/xsl:if&gt;
                                                    &lt;/td&gt;
                                                    &lt;xsl:if test="$tasksAndtools_IsRTL = true()"&gt;
                                                    &lt;td style="padding-right:5px; padding-left: 14px;white-space:nowrap ;"&gt;                                                               
                                                        &lt;a id="TasksAndToolsGo" accesskey="G" title="Go" href="javascript:TATWP_jumpMenu()"&gt;
                                                            &lt;img title="Go" alt="Go" border="0" src="/_layouts/images/icongo01RTL.gif" style="border-width:0px;" onmouseover="this.src='/_layouts/images/icongo02RTL.gif'" onmouseout="this.src='/_layouts/images/icongo01RTL.gif'"/&gt;
                                                        &lt;/a&gt;
                                                    &lt;/td&gt;
                                                    &lt;/xsl:if&gt;
                                                    &lt;xsl:if test="$tasksAndtools_IsRTL = false()"&gt;
                                                    &lt;td style="padding-right:14px; padding-left: 5px;white-space:nowrap ;"&gt;                                                               
                                                        &lt;a id="TasksAndToolsGo" accesskey="G" title="Go" href="javascript:TATWP_jumpMenu()"&gt;
                                                            &lt;img title="Go" alt="Go" border="0" src="/_layouts/images/icongo01.gif" style="border-width:0px;" onmouseover="this.src='/_layouts/images/icongo02.gif'" onmouseout="this.src='/_layouts/images/icongo01.gif'" /&gt;
                                                        &lt;/a&gt;
                                                    &lt;/td&gt;                                                                    
                                                    &lt;/xsl:if&gt;
                                                &lt;/tr&gt;
                                            &lt;/table&gt;
                                        &lt;/xsl:template&gt;
                                        &lt;xsl:template name="MainTemplate.body" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"&gt;
                                            &lt;xsl:param name="Rows"/&gt;
                                            &lt;xsl:for-each select="$Rows"&gt;
                                &lt;xsl:sort select="@Title"/&gt;
                                                &lt;xsl:variable name="GroupStyle" select="'auto'"/&gt;
                                                &lt;option style="display:{$GroupStyle}" value="{ddwrt:EnsureAllowedProtocol(substring-before(@URL, ', '))}" &gt; 
                                                    &lt;xsl:value-of select="@Title"/&gt;
                                                &lt;/option&gt;
                                            &lt;/xsl:for-each&gt;
                                        &lt;/xsl:template&gt;
                                    &lt;/xsl:stylesheet&gt;
    </property>
        <property name="ViewFlag" type="string" />
        <property name="FireInitialRow" type="bool">True</property>
        <property name="TitleUrl" type="string" />
        <property name="NoDefaultStyle" type="string" />
        <property name="ListName" type="string" null="true" />
        <property name="TasksAndToolsWebUrl" type="string">/finance/ratemanagement/ba</property>
        <property name="AllowEdit" type="bool">True</property>
        <property name="ParameterBindings" type="string" />
        <property name="CatalogIconImageUrl" type="string" />
        <property name="Default" type="string" />
        <property name="ChromeState" type="chromestate">Normal</property>
        <property name="DataSourcesString" type="string" />
        <property name="Direction" type="direction">NotSet</property>
        <property name="FilterCategory" type="string">Visible</property>
        <property name="CacheXslStorage" type="bool">True</property>
        <property name="AllowMinimize" type="bool">True</property>
        <property name="UseSQLDataSourcePaging" type="bool">True</property>
        <property name="CacheXslTimeOut" type="int">86400</property>
        <property name="FilterFieldValue" type="string">Yes</property>
        <property name="ExportMode" type="exportmode">All</property>
        <property name="TasksAndToolsListName" type="string">ineedto</property>
        <property name="HelpUrl" type="string" />
        <property name="SampleData" type="string">         &lt;dsQueryResponse&gt;          &lt;NewDataSet&gt;           &lt;Row /&gt;          &lt;/NewDataSet&gt;          &lt;/dsQueryResponse&gt;        </property>
        <property name="AllowClose" type="bool">True</property>
        <property name="DisplayName" type="string" />
        <property name="TitleIconImageUrl" type="string" />
        <property name="TasksAndToolsWidth" type="string">px;</property>
        <property name="ViewContentTypeId" type="string" />
        <property name="XslLink" type="string" null="true" />
        <property name="AllowZoneChange" type="bool">True</property>
        <property name="Hidden" type="bool">False</property>
        <property name="DataFields" type="string" />
        <property name="Title" type="string">See My Organization</property>
        <property name="Width" type="string" />
        <property name="AllowHide" type="bool">True</property>
      </properties>
    </data>
  </webPart>
</webParts>
Just export the webpart from the site and make the change to the XSLT and then import the webpart back into the site.

Custom Theme and Feature Stapling via WSP files

Looking to deploy a custom theme in a solution file? Here’s how to modify the SPThemes.xml file programmatically using Linq to XML. The only thing missing would be clean-up of sites using the theme upon uninstall.
http://blogs.msdn.com/ketaanhs/archive/2009/07/01/modifying-spthemes-xml-programmatically-to-deploy-new-themes-moss-2007-wss-3-0.aspx
Recently used this for a client along with feature stapling to deploy a custom theme and then force all newly created sites to use the theme. I used the WSPBuilder templates for VS2008 (I prefer these above the templates VsWSS).
Step 1: Create a WebApplication scoped feature to handle the FeatureStapling and create a SPFeatureReceiver for the feature to install the feature into the SPThemes file using the technique above.


<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Creator="Chris Quick, Tribridge"
         Description="Forces default Client branding for all sites"
         Hidden="false"
         Id="9DEE24AC-1FF9-4fb3-AC07-2A0D9D616D99"
         Scope="WebApplication"
         Title="Client Default Branding"
         Version="1.0.0.0"
         ReceiverAssembly="Client.SharePoint.Branding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7622be71ccc3f186"
         ReceiverClass="Client.SharePoint.Branding.ClientThemeInstaller">
  <ElementManifests>
    <ElementManifest Location="elements.xml"/>
  </ElementManifests>
</Feature>

Step 2: Setup feature stapling in your ElementManifest file. Make sure the ID of the feature to staple is the ID of the feature that applies the branding (created next).

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <FeatureSiteTemplateAssociation Id="FA5FE9BA-8DCB-40c8-950B-517AC11FCC23" TemplateName="GLOBAL"/>
  <FeatureSiteTemplateAssociation Id="FA5FE9BA-8DCB-40c8-950B-517AC11FCC23" TemplateName="STS#1"/>
</Elements>

Step 3: Create another feature scoped to the Web that will have a feature receiver using a co-worker’s method of applying a theme.

<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
         Creator="Chris Quick, Tribridge"
         Description="Applies Branding to New Sites for Client"
         Id="FA5FE9BA-8DCB-40c8-950B-517AC11FCC23"
         Hidden="False"
         Scope="Web"
         Title="Client Branding Receiver"
         Version="1.0.0.0"
         ReceiverAssembly="Client.SharePoint.Branding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7622be71ccc3f186"
         ReceiverClass="Client.SharePoint.Branding.ClientBrandFeatureReceiver">
  
</Feature>


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;

namespace Client.SharePoint.Branding
{
    class ClientBrandFeatureReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPWeb currentWeb = (SPWeb)properties.Feature.Parent;
            currentWeb.AllowUnsafeUpdates = true;
            currentWeb.ApplyTheme("Client");
            currentWeb.SiteLogoUrl = "/_layouts/images/Client/Client-logo.gif";
            currentWeb.Update();
            currentWeb.AllowUnsafeUpdates = false;
            currentWeb.Dispose();
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPWeb currentWeb = (SPWeb)properties.Feature.Parent;
            currentWeb.AllowUnsafeUpdates = true;
            string theme = currentWeb.Theme;
            string logoUrl = currentWeb.SiteLogoUrl;
            currentWeb.ApplyTheme("none");
            currentWeb.SiteLogoUrl = "/_layouts/images/titlegraphic.gif";
            currentWeb.Update();
            currentWeb.AllowUnsafeUpdates = false;
            currentWeb.Dispose();
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
            // Not being used
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
            // Not being used
        }
    }
}

I’m also taking the opportunity to apply the client’s default logo for the site upon activation of the feature.
Step 4: Put your theme into the solution and make sure it deploys to the TEMPLATE/THEMES folder and place any images into the appropriate folders within TEMPLATE/IMAGES.
Step 5: Build the WSP and deploy to SharePoint for testing. You will need to activate the feature on the Web Application before creating any new sites. When you create new sites, the feature should automatically be activated to deploy the custom theme branding to all news sites on that web application. There is plenty of room for improvement, so comments are welcome!