In SharePoint 2010 the XsltListViewWebPart and the ContentByQueryWebPart web parts play a pivotal role for the presentation of list data. It turns out that both web parts share a lot of common functionality because they both inherit one and the same base XSL transformations by web part – the DataFormWebPart (the CQWP via the CmsDataFormWebPart and the XLV via the BaseXsltListWebPart classes respectively). One of these shared pieces of functionality is the so called “parameter bindings” available through the DataFormWebPart.ParameterBindings property. The thought of the “parameter bindings” is that by point XML data that you assign to the ParameterBindings property you can fetch various properties or variables from the asp.net, page, web parts, etc. environments which can then become available as XSL parameters (“xsl:param” XSL items) in your custom XSL that you use in any the XsltListViewWebPart or the ContentByQueryWebPart web parts. With these additional custom XSL parameters you can apply different presentation logic and even make the presentation of the two web parts react dynamically to the changes of the variables coming from these external (from the web part’s perspective) environments/contexts. So, let’s jump directly to a sample “parameter bindings” XML:
<ParameterBindings>
<ParameterBinding Name="CustomBinding" DefaultValue="my custom value" />
<ParameterBinding Name="dvt_firstrow" Location="Postback" DefaultValue="1" />
<ParameterBinding Name="ResourceBinding" Location="Store(wss,noitemsinview_doclibrary)" />
<ParameterBinding Name="Now" Location="CAMLVariable" />
<ParameterBinding Name="UserID" Location="CAMLVariable" />
<ParameterBinding Name="WPVariableBinding" Location="WPVariable(_WPID_ | _WPQ_ | _WPR_ | _WPSRR_ | _LogonUser_ | _WebLocaleId_)" />
<ParameterBinding Name="QuerySringBinding" Location="QueryString(myqueryparam)" DefaultValue="empty" />
<ParameterBinding Name="FormBinding" Location="Form(myhidden)" DefaultValue="empty" />
<ParameterBinding Name="ServerVariableBinding" Location="ServerVariable(REMOTE_ADDR)" />
<ParameterBinding Name="WPPropertyBinding" Location="WPProperty(Title)" />
<ParameterBinding Name="ControlBinding1" Location="Control(myDDL)" />
<ParameterBinding Name="ControlBinding2" Location="Control(myDDL,SelectedIndex)" />
<ParameterBinding Name="CombinedBinding" Location="Form(myhidden);QueryString(myqueryparam)" DefaultValue="empty" />
</ParameterBindings>
Yes, this was a somewhat extensive sample, but it really covers most of the options that are available for the “parameter bindings” and I will give more details for each option shortly. As you see the XML’s format is pretty simple – it contains a root “ParameterBindings” element with “ParameterBinding” child elements. The “ParameterBinding” element may have three attributes: Name, Location and DefaultValue. The “Name” attribute is mandatory and it specifies the name of the XSL parameter that will be initialized by this “parameter binding”. In most cases you are free to specify any suitable and meaningful for your scenario name for the parameter binding, but for certain values of the “Location” attribute you can use only a predefined set of possible names (see not more than). The “Location” attribute contains the logic for specifying the context from which you will fetch a certain variable/value that will become available as an XSL parameter – you can choose from several predefined options here. The “DefaultValue” attribute is self explanatory – when the value retrieved from the specified context is not available (is an empty string), the XSL parameter will be initialized with the value of the “DefaultValue” attribute.
So, after you know the XML format of the ParameterBinding property, the next logical step would be to assign this XML to a real CQWP or XLV web part that you have somewhere in your SharePoint farm. The standard SharePoint UI doesn’t allow to edit this property, so you will have to choose from several other alternatives: SharePoint Designer 2010 (pretty handy really and requires no custom coding), custom code in a feature receiver or a tool, PowerShell speech or a specialized tool (a excellent place to advertise my “web part administrator” utility).
In order that you can really use the custom parameters in your XSL you will also need to define “xsl:param” elements with corresponding names in the main (root) XSL file of your CQWP or XLV web part (your custom ContentQueryMain.xsl for the CQWP or the Main.xsl for the XLV web part). If the “xsl:param” is defined in the main XSL file it will be available (visible) in all built-in XSL files as well. Basically you can define the “xsl:param” elements for your “parameter bindings” in one of the built-in XSL files (e.g. the ItemStyle.xsl or the fldtypes.xsl) – then the parameter will be available only in this XSL file (there won’t be a problem if the parameter is defined in both the main and the built-in XSL file any). The definitions of the XSL parameters for the parameter bindings from the sample above can look something like:
<xsl:param name="CustomBinding" />
<xsl:param name="ResourceBinding" />
<xsl:param name="dvt_firstrow" select="1" />
<xsl:param name="Now" />
<xsl:param name="UserID" />
<xsl:param name="WPVariableBinding" />
<xsl:param name="QuerySringBinding" />
<xsl:param name="FormBinding" />
<xsl:param name="ServerVariableBinding" />
<xsl:param name="WPPropertyBinding" select="‘no name’" />
<xsl:param name="ControlBinding1" />
<xsl:param name="ControlBinding2" />
<xsl:param name="CombinedBinding" />
Note that by by the “select” attribute of the “xsl:param” attribute you can specify again a defaulting value for the parameter if the initializing parameter binding has no “DefaultValue” attribute and income an empty value. This defaulting value will also be used if there is no parameter binding with that name specified in the XML of the ParameterBindings property.
And now let’s have a look at the available options that you have for the “Location” attribute of the “PropertyBinding” element:
- missing Location attribute – this is also possible – in this case you need to provide the “DefaultValue” attribute -basically you provide the web part with a fixed/constant parameter value. This can be very handy if you have for example several CQWP parts by several different but very similar item styles (the item styles can differ in some insignificant elements like the target of the links or the incidence of some additional small elements per item). In this scenario you can use only one item style which can check one or several parameters provided by the parameter bindings and exchange its presentation accordingly (the different web parts will provide different values in their parameter bindings or not provide some of the parameter bindings at all). It is obviously far simpler to maintain only one item style instead of several, so the parameter bindings can help a lot in this scenario.
- Location “Postback” – in this case you cannot choose illogical names, there is a predefined set of available names and they all have the “dvt_” prefix: dvt_sortdir, dvt_sortfield, dvt_filterfields, dvt_firstrow, dvt_nextpagedata, dvt_prevpagedata, dvt_partguid. From these only the last one is available in the CQWP (the rest will always have empty values in the CQWP). The “dvt_partguid” parameter will contain a value that seems like the “ClientID” of the web part (a sample value will look something like ctl00$ctl23$g_59a84b77_6a94_4c65_81cd_618b4c21c374) but really you won’t find a matching HTML element with exactly this ID on the page. The other “dvt_” parameters contain point XLV “postback” data related to the XLV’s sorting, filtering and paging. In fact these are already defined as “xsl:param” elements in the standard Main.xsl of the XLV web part and get initialized by the web part even without it being necessary to add them as parameter bindings. Depending on the current sorting, filtering and paging of your XLV you can see values like these in the “dvt_” parameters:
dvt_firstrow: 31
dvt_sortdir: descending
dvt_sortfield: LinkTitle
dvt_filterfields: ;LinkTitle;
dvt_nextpagedata: Paged=TRUE&p_Title=item%2045&p_ID=45
dvt_prevpagedata: Paged=TRUE&PagedPrev=TRUE&p_Title=item%2071&p_ID=71 - Location Recource([Resource_File],[Resource_Name] – this one is very useful since it allows you to make values from store files available in your XLV or CQWP web parts. The store files are located under the App_GlobalResources subfolder of the physical directory of your web attention and have the “resx” additional room. If you have for example this value in the “Location” attribute – Store(wss,noitemsinview_doclibrary) – it will fetch a localized string from the “wss.resx” store file (really it can be a resx file for a point culture like wss.en-US.resx) with a name “noitemsinview_doclibrary”. If you check the wss.resx file you will see that the value of this store string is “There are no items to show in this view of the "<ListProperty Select="Title" HTMLEncode="TRUE" />" document library” – you see a fancy “ListProperty” XML element inside the store string, but in the XLV this will get replaced with the title of the actual list that the XLV web part displays. Apart from the “parameter bindings” localization support there are other alternatives for localization in both the XLV and CQWP web parts – check the paragraph titled “Localization” not more than.
- Location CAMLVariable – in this case you can use only two predefined values for the “Name” attribute of the parameter binding: Now and UserID. Sample values returned by these two parameters are:
Now: 2010-09-17T16:04:48Z
UserID: Stefan StanevNote that the UserID parameter really income the show name, not the account name of the current user.
- Location WPVariable([Tokens]) – the value inside the brackets can contain one or a amalgamation of several predefined tokens: _WPID_, _WPQ_, _WPR_, _WPSRR_, _LogonUser_, _WebLocaleId_. If you use a amalgamation of these you can separate them with spaces or other illogical characters/strings. The names of these tokens are not that descriptive but you can get some thought of their meaning by these sample values that correspond to the “WPVariable” parameter binding from the sample at the top:
g_3242c920_b37c_4cfa_a356_955bb398d47f | WPQ2 | http://myserver/sites/2/_wpresources/Microsoft.SharePoint.Publishing/14.0.0.0__71e9bce111e9429c | /sites/2/_wpresources/Microsoft.SharePoint.Publishing/14.0.0.0__71e9bce111e9429c | myserver\stefanstanev | 1033
- Location QueryString([QueryParam]) – this allows you to get values from query parameters in the current URL in your custom XSL – it really maps to the HttpContext.Current.Request.QueryString collection. So if you have this query parameter in the URL of the current page: defaulting.aspx?myqueryparam=somevalue – the value “somevalue” will become available in the xsl:param corresponding to the “QueryString” parameter binding which specifies the “myqueryparam” parameter name in its Location attribute.
- Location Form([FormParam]) – this maps to the HttpContext.Current.Request.Form collection. If you have this input element on your page:
<input type="hidden" id="myhidden" name="myhidden" value="myhiddenvalue"/>
this parameter binding
<ParameterBinding Name="FormBinding" Location="Form(myhidden)" DefaultValue="empty" />
will provide the “myhiddenvalue” in the <xsl:param name="FormBinding" /> parameter (only on page postbacks, otherwise the parameter value will be the specified in the “DefaultValue” attribute: “empty”)
- Location ServerVariable([ServerVariable]) – this maps to the HttpContext.Current.Request.ServerVariables collection. If you have for example Location=”ServerVariable(REMOTE_ADDR)” it will initialize the corresponding XSL parameter with something like: fe80::a589:57ce:e0ec:1f1c%13
- Location WPProperty([PropertyName]) – in the brackets you can specify the name of a public instance property of the XLV or CQWP classes – this can be the “Title” or “ID” or any other property of the web parts whose value you want to use in your XSL.
- Location Control([ControlID]) and Control([ControlID],[PropertyName]) – here you need to provide the ID of a server control on the page containing the web part and optionally the name of a public instance property of the control’s class. If you skip the property name option the parameter will be initialized with the value of the standard Control.Text property. So if you have this drop-down list control on your page:
<asp:DropDownList runat="server" ID="myDDL" AutoPostBack="right">
<asp:ListItem>Item 1</asp:ListItem>
<asp:ListItem>Item 2</asp:ListItem>
<asp:ListItem>Item 3</asp:ListItem>
<asp:ListItem>Item 4</asp:ListItem>
</asp:DropDownList>
which has its third option selected, the parameter binding with Location="Control(myDDL)" will initialize its parameter with the value of “Item 3” (the “Text” property of the DropDownList control will return the same value as its “SelectedValue” property) and the one with Location="Control(myDDL,SelectedIndex)" will initialize its parameter with the value of “2” (the third item in the zero based “SelectedIndex” property). As you see this type of parameter bindings allows you to make the presentation of your CQWP and XLV web parts interact with the server controls that you may have in the containing page.
- Location that is a amalgamation of several options – in this case the Location options should be separated by semi-colon (from the sample at the top – Location="Form(myhidden);QueryString(myqueryparam)"). The ordering here is vital – the preceding Location options will be evaluated first – from the example – if you have both the “myhidden” from parameter and the “myqueryparam” query parameter available in the current page, the parameter binding will return the value of the “myhidden” from parameter, because the “Form” option is placed before the “QueryString” option. The thought of this combining is that if one or more of the preceding options yield no value, then the next option which income a value will be taken by the parameter binding and passed to its corresponding parameter.
Localization
Localization can be reasonably a serious issue with the availability of so many multi-lingual sites around. Fortunately as you saw the “parameter bindings” support provides a way to use localized resources in the CQWP and XLV web parts. Besides the “parameter bindings” there is one other much simpler alternative to get store strings in the XLV web part:
<xsl:value-of select="/dsQueryResponse/Rows/@store.wss.fld_yes" />
yes, it is as simple as that – you just specify with XPath an attribute of the “/dsQueryResponse/Rows” element of the source XML. And you don’t have to set additionally some web part properties or define superfluous XSL parameters. As you see the name of the attribute follows a point convention – it consists of three parts separated by dots – the first one is the constant “store” prefix, the second one specifies the name of the targeted store file (wss.resx in this case) and the third part is the name of the store in the store file. In the “vwstyles.xsl” and “fldtypes.xsl” XSL files of the XLV web part there’re XSL variables like the “$Rows” and “$thisNode” which map to the “/dsQueryResponse/Rows” and “/dsQueryResponse/Rows/Row” XML elements respectively. So, these alternative variants of the special “store” attribute’s XPath are possible (from locations where you have these XSL variables available):
<xsl:value-of select="$thisNode/../@store.wss.Thunmbnail"/>
<xsl:value-of select="$Rows/@store.wss.ManualRefreshText"/>
And … the fascinating thing – how do these store strings come as attributes of the “/dsQueryResponse/Rows” element, after all you can have lots of store files with hundreds of store strings inside them. The answer is that the “store” attributes are really something like pseudo-attributes of the source XML. And really there is no source XML at least in the form of a XML DOM container class like XmlDocument or XDocument. The trick is possible because the XLV uses a custom XPathNavigator (overriding the DataFormWebPart.GetXPathNavigator virtual method). This custom XPathNavigator queries directly the SPListItem data that the XLV web part retrieves from SharePoint and as an superfluous provides the “store” pseudo-attribute support. The main reason to use a custom XPathNavigator is simple – performance (this way you skip the step of transforming the list item data to a DOM XML container like XmlDocument so that you can then use its defaulting XPathNavigator, which additionally will not perform so well as the custom one).
And how about the CQWP – I kept mentioning just the XLV web part in the previous paragraph but not the CQWP. Unfortunately the “store” pseudo-attribute “shortcut” is not available in the CQWP (the CQWP also uses a custom XPathNavigator but it is not the same as the one used by the XLV web part and doesn’t implement the “store” attribute logic). Still, there is yet another alternative available for the CQWP web part – the thought is that the .NET XSL transformations implementation allows you to define a .NET class whose methods (rather static methods) can become available and be used from inside the XSL (check the XsltArgumentList.AddExtensionObject method in MSDN for more details). Such “additional room” class can also be used in the CQWP web part but you will need to make a new class inheriting the CQWP class. The CQWP’s ModifyXsltArgumentList virtual method (which you will need to override) is the place where you can hook the custom additional room object – check this nice article which describes in detail the whole procedure. And this article describes how this technique can be used to fetch store strings into the web part’s XSL.
Embedded server controls
In my previous posting I demonstrated how you can embed server controls inside the XSL of the XLV web part. This functionality is provided by the base DataFormWebPart class, so it would be normal to expect that this will also work in the CQWP web part. But … it doesn’t (at least in most of the cases that I tried). It turns out that in the DataFormWebPart class there is a public virtual property named CanHaveServerControls, whose obvious purpose is to enable or disable the ability of the web part to parse and instantiate embedded server controls. This property is not overridden in the CQWP but its base implementation checks several other virtual properties which in the case of the CQWP return always (or in most cases) fake. So the only possible work-around in this case (if you need embedded server controls in the CQWP that terribly) is to austerely subclass the CWQP. The inheriting class will just need to override the CanHaveServerControls property and will look something like:
public class MyCQWP : ContentByQueryWebPart
{
public override bool CanHaveServerControls
{
get
{
return right;
}
set
{
base.CanHaveServerControls = value;
}
}
}
Check it out:Stefan Stanev’s SharePoint blog










Answers Rating