Consider the following scenario :
- An existing content type spread across multiple lists
- A CQWP is required to query the items of that content type and group the results by the list which they belong to
- The group headings have to be links to the actual list
- There should be no visible change to the existing stuff
- There is an existing ItemAdded event handler attached to the content type
The challenge is, that by default the items returned from the CQWP don’t actually know much more about the parent list apart from the ListID that is returned as an attribute of the row element. You would think the list guid is all you need to identify the list instance, which it completely is, but since you are rendering XML with XSL Style Sheets, you don’t really have much flexibility in pulling actual information about that list.
I had a browse around the net to see how other people get the parent list name of row items – the most viable approach was the event handler. Since the already released version of the solution had an event receiver against the content type, my best option was to modify it to give me some information about the parent list.
- I added two hidden fields to the content type to satisfy the “no visible change” requirement – one for the list name and the other for the list URL (site collection relative).
- I modified the event handler to populate them
The next challenge was that the CQWP won’t see the hidden fields in the UI, so I had to set them manually.
The following properties inside the .webpart file of my CQWP allows me to add those fields to the grouping functionality of the web part:
1: <property name="AdditionalGroupAndSortFields" type="string">ParentListName;ParentListUrl</property>
2: <property name="CommonViewFields" type="string">ParentListName, Text;ParentListUrl, Text</property>
3: <property name="GroupBy" type="string">ParentListName</property>
This MSDN article gives a good explanation on how to use these properties: http://msdn.microsoft.com/en-us/library/aa981241.aspx
The CommonViewFields property tells the query to return further fields into the row xml. You can reference the values of these inside the XSL. The AdditionalGroupAndSortFields will allow you to set it in the Group By section in the UI.
Here is the template inside my header XSL Style Sheet that renders the group heading as a link:
1: <xsl:template name="CustomLinkedHeader" match="*" mode="header">
2: <div class="groupheader item medium">
3: <a>
4: <xsl:attribute name="href">
5: <xsl:value-of select="@ParentListUrl"/>
6: </xsl:attribute>
7: <xsl:call-template name="OuterTemplate.GetGroupName">
8: <xsl:with-param name="GroupName" select="@*[name()=$Group]"/>
9: <xsl:with-param name="GroupType" select="$GroupType"/>
10: </xsl:call-template>
11: </a>
12: </div>
13: </xsl:template>
The rest of the XSL handles the parent list name automatically. The good thing is that the web part won’t display headings where items are not returned as they don’t exist in the result set. It also provides you the ability to filter on fields – great functionality.
That’s pretty much it. The CQWP is REALLY powerful, I love it and I now find XSLT stuff really fun too.