Extending Base Xslt Web Parts with custom control bindings

What a long title! Maybe it requires a little bit of explanation. Here it is.

First of all, by Base XSLT Web Parts I mean a whole family of OOTB SharePoint Web Parts that leverage XSLT transformation to produce markup out of XML data coming from a data source. If you dig into the class hierarchy starting, say, from the XsltListViewWebPart or the ContentByQueryWebPart, you’ll find something like this:


If you navigate up the hierarchy, you’ll see that several features are implemented by the base DataFormWebPart class. One of these features is the capability to resolve dynamic parameters, i.e. values that come from query string, postback parameters and a few other sources.

More accurately speaking, the sources for dynamic parameters and the logics of parameters substitution are defined by an internal method of DataFormWebPart, named ResolveParameterBindingsToParameterValues.

Below you can find an excerpt of the method implementation:


As you can observe, you can actually set the ParameterBindings web part property to an XML string with proper semantics, thus inject dynamic values as XSLT parameters for the rendering transformation.

You can choose from the following sources:

  • Query String
  • Postback Parameters
  • Form Parameters
  • Web Part Connections
  • Web Part Variables
  • Resources
  • Server Variables
  • CAML Variables
  • Controls

Since XSLT and XPath are a powerful query and transformation engine, you will be able to define conditional blocks and data manipulation expressions based on these dynamic bindings.

But there’s more!

Did you notice the last binding source, the Control source?

The way it works is easy: you have to specify the server ID of an ASP.NET control available on the page and the name of one of its properties. The implementation of DataForWebPart will recursively walk the ASP.NET control tree upwards until it finds a control with the specified ID: then, with a couple of Reflection tricks the value of the specified property will be retrieved and made available to the web part rendering.

You can try this behavior adding, say, a TextBox or a DropDownList control on the page and using the value coming from the Text and SelectedValue properties respectively.

What I like most of this approach (hence the reason of this post’s title) is that you are not limited to OOTB web controls: you can “attach” pretty much any kind of control which exposes a readable property in a plain format (complex data types would be serialized using the ToString method, so the usefulness of these properties really depends on the overridden implementation of the ToString method).

By any kind of control I mean any kind of controls, including any custom control that you may develop in order to extend the XSLT* Web Parts capabilities.

From the extensibility point of view, this means that you (as a developer) can write a suite of simple web controls that are not meant to be used for their output markup, but just as a data source for existing, SharePoint web parts. Then, a colleague who is capable of building no-code solutions using SharePoint Designer will be able to leverage your extensions, using CQWPs or CoreResultsWPs without reinventing the wheel (i.e. building everything from scratch).

Nice, isn’t it?

Below you can find a sample implementation of a web control that exposes the current UI culture, and that may be useful in multilingual scenarios where you want your aggregation web parts (CQWPs, etc…) to behave differently according the the selected language.

But you can easily imagine that this technique can be applied in an infinite number of ways!

   1:  namespace GreenTeam.SharePoint2010.Multilanguage
   2:  {
   3:    public class CultureControl : Control
   4:    {
   5:      [WebBrowsable]
   6:      public Int32 UICultureLCID 
   7:      {
   8:        get
   9:        {
  10:          return Thread.CurrentThread.CurrentUICulture.LCID;
  11:        }      
  12:      }
  14:      [WebBrowsable]
  15:      public Int32 CultureLCID
  16:      {
  17:        get
  18:        {
  19:          return Thread.CurrentThread.CurrentCulture.LCID;
  20:        }
  21:      }
  23:      protected override void Render(HtmlTextWriter writer)
  24:      {
  25:        // Do not emit markup at all!
  26:      }
  27:    }
  28:  }

Leave a Reply

Your email address will not be published. Required fields are marked *