Tom Clarkson is a SharePoint consultant and entrepreneur based in Sydney, Australia.

Contact Details

Links



Recent Searches



Archives




Past Posts







RSS Feed

Alphabetical Paging on a SharePoint List View

SharePoint 2007
Friday February 15 2008

One of the requirements I have had to work on lately is reproducing elements of a Domino UI in sharepoint. That happens to include a long list of sites with links at the top providing the ability to view sites starting with a particular letter.

 

This of course is quite different from the standard SharePoint paging/filtering/grouping, which is based on page numbers and full text values.

 

 

 

The first approach I tried was to add a filter provider web part implementing ITransformableFilterValues as documented by Ton Stegeman - MOSS 2007 Filter webparts part 1 - create your own provider and consumer .

 

Unfortunately, the out of box list view web part doesn't provide particularly good support for filter providers. Sending the connection from the filter provider fails with the error "AvailableLinks did not implement the GetInitEventArgs method". Setting up the connection the other way works, but is still quite limited. You can't filter on a url field, the filter operator is always equals, and you can only filter on a column that is visible in the current view.

 

The first two constraints mean that we will need to create an additional column "FirstLetter" that is calculated based on the url title.

 

The third constraint means that we will need to use query string filters instead of a connected web part. Query string filters do have a few limitations, in particular that they apply to every list on the page. However, this will not be a problem in this case as the page will only contain one list view.

 

The filter portion is easy enough. In the web part render method, create a series of links in the format

 

<a href="?FilterField1=FirstLetter&FilterValue1=A">A</a>

 

AlphabetFilterWebPart.cs Render Method

 

protected override void Render(HtmlTextWriter writer)
        {
            try
            {
 
                writer.Write(string.Format("<a href=\"?FilterClear=1\">{1}</a> ", "0", "All"));
                writer.Write(string.Format("<a href=\"?FilterField1=FirstLetter&FilterValue1={0}\">{1}</a> ", "0", "0-9"));
 
                foreach (char c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray())
                {
                    writer.Write(string.Format("<a href=\"?FilterField1=FirstLetter&FilterValue1={0}\">{1}</a> ", c, c));
                }
 
            }
            catch (Exception ex)
            {
                writer.Write(ex.Message + " " + ex.StackTrace);
            }
        }

 

Populating the FirstLetter column is a little more complex. A calculated field would be ideal, but that won't work for a links list as the URL is a complex field type and not supported in a calculated field formula.

 

The easiest way to handle this is with an event handler. When the link is added or updated, use .net code to update the FirstLetter field.

 

All the bits not shown are the defaults created by the WSPBuilder templates.

 

Elements.xml

 

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="WebPartPopulation" Url="_catalogs/wp" RootWebOnly="TRUE">
    <File Url="AlphabetFilterWebPart.webpart" Type="GhostableInLibrary">
      <Property Name="Group" Value="MyGroup"></Property>
      <Property Name="QuickAddGroups" Value="MyGroup" />
    </File>
  </Module>
  <Receivers ListTemplateId="103">
    <Receiver>
      <Name>AddFirstLetter</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>AlphabetFilter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1f633ef6b7fa5501</Assembly>
      <Class>AlphabetFilter.FirstLetterEventHandler</Class>
      <Data></Data>
      <Filter></Filter>
    </Receiver>
    <Receiver>
      <Name>UpdateFirstLetter</Name>
      <Type>ItemUpdated</Type>
      <SequenceNumber>10000</SequenceNumber>
      <Assembly>AlphabetFilter, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1f633ef6b7fa5501</Assembly>
      <Class>AlphabetFilter.FirstLetterEventHandler</Class>
      <Data></Data>
      <Filter></Filter>
    </Receiver>
  </Receivers>
    </Elements>
 
 

FirstLetterEventHandler.cs

 

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Text.RegularExpressions;
 
namespace AlphabetFilter
{
    public class FirstLetterEventHandler:SPItemEventReceiver
    {
        private void SetFirstLetter(SPListItem item)
        {
            if (!item.Fields.ContainsField("URL")) return;
            if (!item.Fields.ContainsField("FirstLetter")) return;
            SPFieldUrlValue urlvalue = new SPFieldUrlValue(""+item["URL"]);
 
            string firstlettervalue = "" + item["FirstLetter"];
            string linktitle = urlvalue.Description;
            if (                
                !string.IsNullOrEmpty(linktitle) 
                
                && (
                // no first letter
                string.IsNullOrEmpty(firstlettervalue) 
                // first letter does not match and is not 0
                || (firstlettervalue != "0" && !linktitle.StartsWith(firstlettervalue, StringComparison.InvariantCultureIgnoreCase))
                // firstlettervalue == 0 iff  title starts with number and first letter is not 0
                || ((firstlettervalue == "0") == (Regex.IsMatch(linktitle, "^([a-z]|[A-Z]).*"))))
 
                )
            {
 
                // to simplify the filter web part, the value set will always be 
                // an uppercase letter or 0 for other characters.
                if (Regex.IsMatch(linktitle, "^([a-z]|[A-Z]).*"))
                {
                    item["FirstLetter"] = ("" + linktitle[0]).ToUpper();
                }
                else
                {
                    item["FirstLetter"] = "0";
                }
 
                item.Update();
            }
 
        }
 
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
            SetFirstLetter(properties.ListItem);
 
        }
 
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            base.ItemUpdated(properties);
            SetFirstLetter(properties.ListItem);
        }
 
    }
}

Once this is working, you will want to remove the FirstLetter field from the form. To do this:

1.        Enable content type management on the links list

2.        Edit the link content type

3.        Edit FirstLetter and set it to hidden so it will not appear on forms.

Another option I looked at was using Ishai's Advanced Content Query web part, as that is already in use on the site and does handle filters properly. However, that would mean replacing the good parts of the out of box list view as well as the bad parts, making it less desirable than the query string filter solution.

 

If you need to add the paging functionality to another sort of list, filtering on the title column, create FirstLetter as a calculated column with the formula

 

=IF(ISNUMBER(VALUE(LEFT(Title,1))), "0", LEFT(Title,1))

 

 

Comments

On 14 May 2008 07:26, Uzma said:
Hi Tom, 

This is exactly what I'm looking for to deploy on a site that I'm working on. However, I would like to ask, about the above steps.. should they all take place in Sharepoint Designer? I'll look through my files to make sense of the .cs and .xml files and where they need to go. Any tips, starter points will be helpful :)
On 02 Jun 2008 01:52, Tom Clarkson said:
This is all done in Visual Studio using WSPBuilder. You can do code in SharePoint Designer, but I don't recommend it.
On 20 Aug 2008 01:35, said:
On 07 Oct 2008 12:26, cristina said:
Hi tom,
I have installed the visual studio 2005 and Sharepoin designer.. but i do not know how to get the WSPBuilder?

Any tips what stuff i need to do or get to use that ....

Regards,
Cristina 
On 07 Oct 2008 12:58, Tom Clarkson said:
Try the link on the left of this page.
On 30 Oct 2008 02:07, Sally4000 said:
Hello,
thanks for ur very useful article.
will you please explain what is next after implementation?? how we have to deploy it to sharepoint t obe able to see it on the platform ??

Many Thanks
On 30 Oct 2008 10:06, Tom Clarkson said:
Deployment method will depend on your environment, but if you package it with WSPBuilder deployment is usually just a matter of running the installer.
On 11 Nov 2008 11:22, Sally4000 said:
Hello,

which filter provider web part you have choose?? 
(Business Data Catalog Filter 
Choice Filter 
Current User Filter 
SharePoint List Filter)
On 11 Nov 2008 11:24, Sally4000 said:
Hello,

which filter provider web part you have choose?? 
(Business Data Catalog Filter 
Choice Filter 
Current User Filter 
SharePoint List Filter)
On 12 Nov 2008 09:43, Tom Clarkson said:
This is a custom web part, not one of the out of box filter web parts. It doesn't even use the filter provider / web part connections system - it just renders some links with appropriate stuff in the query string.
On 06 Dec 2008 11:14, joao said:
How can i use the query string method to filter a moss list using a custom field type (eg: URL+Description+Title+Target) but based on just the value of URL ? Do i need to create a calculated column that is filled on ItemCreated with the value of the URL and then filter by that Field ?
On 30 Dec 2008 01:40, Yuk said:
Hi, Tom

Thank you, it's very usefull.
On 31 Dec 2008 12:28, Yuk said:
Hallo Tom,

Can you tell me where did you put the Elements.xml? 
On 31 Dec 2008 08:26, Yuk said:
Hallo Tom,

Can you tell me where did you put the Elements.xml? 
On 27 Jan 2009 05:47, Tom Clarkson said:
Elements.xml goes in the feature folder - edit the elements.xml created by WSPBuilder.
On 27 Jan 2009 05:49, Tom Clarkson said:
Url based filtering is fairly limited - equals only, no other operators. So yes, you may need to create a calculated column that provides the simple field to filter by.
On 20 Apr 2009 06:23, Samir said:
Hello Tom,

does this solution work for WSS3.0


On 20 Apr 2009 07:14, Samir said:
Hello Tom,

does this solution work for WSS3.0


On 20 Apr 2009 08:29, Samir said:
Hello Tom,

does this solution work for WSS3.0


On 20 Apr 2009 09:20, Samir said:
Hello Tom,

does this solution work for WSS3.0


On 21 Apr 2009 12:50, Samir said:
Hello Tom,

does this solution work for WSS3.0


On 27 Apr 2009 07:22, gem said:
Hi ,
I my system Wspuilder is not there. I have created webpart for alphabets and, classlirary for eventhandler, futures and elements xml files.
It is showng error like 

"failed to instantiate file "<wepartName>.wepart" from module "wepartpopulation" : source path "<wepartName>.webpart" notfound.

And, I have no idea about "wepartpopulation" modules' job.

So, please let me know the solution.
On 27 Apr 2009 07:23, gem said:
Hi ,
I my system Wspuilder is not there. I have created webpart for alphabets and, classlirary for eventhandler, futures and elements xml files.
It is showng error like 

"failed to instantiate file "<wepartName>.wepart" from module "wepartpopulation" : source path "<wepartName>.webpart" notfound.

And, I have no idea about "wepartpopulation" modules' job.

So, please let me know the solution.
On 30 Apr 2009 09:52, pra said:
Can you briefly expali me aout this 

  <Module Name="WebPartPopulation" Url="_catalogs/wp" RootWebOnly="TRUE">

- I am new to sharepoint..
On 02 May 2009 04:39, said:
"Elements of type 'Receivers' are not supported at the 'Site' scope.  This feature could not be installed."	

I am getting this error while deploying (deployement failed). What could be the reason?
On 02 May 2009 04:56, said:
"Elements of type 'Receivers' are not supported at the 'Site' scope.  This feature could not be installed."	

I am getting this error while deploying (deployement failed). What could be the reason?
On 02 May 2009 05:46, said:
"Elements of type 'Receivers' are not supported at the 'Site' scope.  This feature could not be installed."	

I am getting this error while deploying (deployement failed). What could be the reason?
On 02 May 2009 06:28, said:
"Elements of type 'Receivers' are not supported at the 'Site' scope.  This feature could not be installed."	

I am getting this error while deploying (deployement failed). What could be the reason?
On 06 Nov 2009 02:59, Lotumvka said:
comment1 
On 09 Nov 2009 12:38, Olxfofad said:
comment4 
On 18 Nov 2009 02:46, ergtyh said:
<a href="http://wiki.openg.org/User:Scenehandley">angel loliata</a> asdfasfds <a href="http://www.metacafe.com/channels/profieedprosiev">lolita biz</a>

On 19 Nov 2009 01:10, GUqqOGRiuyxGPvQ said:
270_114.txt;8;12
On 23 Nov 2009 05:24, StenZexfoext said:
Dating livingston, Gay dating san diego, Dating hooversville:
[url=http://dating-agenda.datinginrus.com/]dating agenda[/url],
[url=http://any-dating-site.datinginrus.com/]any dating site[/url],
[url=http://dating-coden.datinginrus.com/]dating coden[/url].
Dating carrolls. Dating oketo. Dating west bradenton.
On 13 Feb 2010 11:22, nima said:
very usefull. thanks alot

Leave a comment