Using the XsltListViewWebPart with a Custom Query


In a recent customer project I had the need for a ListViewWebPart which can be used with a custom query with some values coming from the current user profile. I had to query a huge List and only to set a filter was not an option.

I didn’t want to develop a custom ListViewWebPart because there is so much functionality in the OOB XsltListViewWebPart and no other control or WebPart coming with SharePoint 2010 has this rich list view features.

My first approach was to look if anybody has already published a solution for that. The only thing I found was a WebPart that renders the XsltListViewWebPart as a sub-control. But this approach doesn’t work with more than one of this WebParts in a page. So I started my own journey …

Looking from where the query comes and is it possible to change it on demand:

  • Create a custom list name it Test with only a Title column and a few items.
  • Then create a new page and add the Test XsltListViewWebPart.
  • In the Edit Web Part Window select the All Items view

 

When you click OK and go once again to Edit Web Part you can see that the Selected View setting has changed to <Current view>:

Hmm, I didn’t select that …

Ok, let’s have look behind the scenes: with the help of a very cool tool from codeplex (http://webpartmanager.codeplex.com/ ) you can examine the actual values of the properties of the WebPart on your page:

The first interesting thing is that the value of the ViewGuid of my Test XsltListViewWebPart is not the Guid of the All Items view which I selected. When SharePoint creates a XsltListViewWebPart on a page or when you change the view setting, SharePoint automatically creates a hidden copy of the given view (default or selected) and uses this hidden view for all actions of the XsltListViewWebPart.

The second interesting thing is that the property XmlDefinition contains a copy of the CAML declaration of this hidden view.

When you examine the XmlDefinition, you will find that there is also a Query element:

<View
Name={1CD069D1-FF94-4F77-9092-52E2BD9300FC}
MobileView=TRUE
Type=HTML
Hidden=TRUE
DisplayName=“”
Url=/SitePages/TestPage.aspx
Level=1
BaseViewID=1
ContentTypeID=0x
ImageUrl=/_layouts/images/generic.png>

<Query>

<OrderBy>

<FieldRef
Name=ID/>

</OrderBy>

</Query>

<ViewFields>

<FieldRef
Name=Attachments/>

<FieldRef
Name=LinkTitle/>

</ViewFields>

<RowLimit
Paged=TRUE>30</RowLimit>

<Toolbar
Type=Freeform/>

</View>

 

Whowh, let’s go and write some code …

The short story of a lot of tries is: it does not work. Yes you can change the XmlDefinition property, but the XsltListViewWebPart does not use it after you have changed it.

But there is another option which works! (with one exception: filtering)

You can change the the SelectCommand of the XsltListViewWebPart.DataSource:


SPDataSource ds = xsltListViewWebPart.DataSource as
SPDataSource;


if (ds != null)

{


string xmlSelectCommand = string.Empty;


XmlDocument viewXmlDoc = new
XmlDocument();

viewXmlDoc.LoadXml(ds.SelectCommand);


XmlNode queryNode = viewXmlDoc.DocumentElement.SelectSingleNode(“Query”);

queryNode.InnerXml = TextBoxQuery.Text;

xmlSelectCommand = viewXmlDoc.OuterXml;


ds.SelectCommand = xmlSelectCommand;

I have written a small WebPart just for demonstration purpose which allows you to change the query on demand:

In the first step the WebPart gets a reference of the first XsltListViewWebPart on the page:

using System;

using System.ComponentModel;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.WebPartPages;

 

namespace BR.SP.LVQueryWebPart.LVQueryWP

{

[ToolboxItemAttribute(false)]


public
class
LVQueryWP : System.Web.UI.WebControls.WebParts.WebPart

{


// Visual Studio might automatically update this path when you change the Visual Web Part project item.


private
const
string _ascxPath = @”~/_CONTROLTEMPLATES/BR.SP.LVQueryWebPart/LVQueryWP/LVQueryWPUserControl.ascx”;

 


protected
override
void CreateChildControls()

{


Control control = Page.LoadControl(_ascxPath);

Controls.Add(control);

 


LVQueryWPUserControl lvqc = control as
LVQueryWPUserControl;


if (lvqc != null)

{


foreach (System.Web.UI.WebControls.WebParts.WebPart webPart in
this.WebPartManager.WebParts)

{


XsltListViewWebPart xlvwp = webPart as
XsltListViewWebPart;


if (xlvwp != null)

{

lvqc.XsltListViewWebPart = xlvwp;


break;

}

}

 

}

 

}

}

}

In the Control property XsltListViewWebPart the control registers for the DataBinding event of the XsltListViewWebpart:

 


public
XsltListViewWebPart XsltListViewWebPart

{


get { return xsltListViewWebPart; }


set

{

xsltListViewWebPart = value;

xsltListViewWebPart.DataBinding += new
EventHandler(xsltListViewWebPart_DataBinding);

}

}

 

and when the event is raised, the query is changed to the custom query:

 


void xsltListViewWebPart_DataBinding(object sender, EventArgs e)

{


if (TextBoxQuery.Text.Trim().Length > 0 && xsltListViewWebPart != null)

{


SPDataSource ds = xsltListViewWebPart.DataSource as
SPDataSource;


if (ds != null)

{


string xmlSelectCommand = string.Empty;


XmlDocument viewXmlDoc = new
XmlDocument();

viewXmlDoc.LoadXml(ds.SelectCommand);


XmlNode queryNode = viewXmlDoc.DocumentElement.SelectSingleNode(“Query”);

queryNode.InnerXml = TextBoxQuery.Text;

xmlSelectCommand = viewXmlDoc.OuterXml;

ds.SelectCommand = xmlSelectCommand;

 

xsltListViewWebPart.DisableColumnFiltering = true;

}

}

}

There is one thing that does not work with this approach: Filtering

Ok, that’s not precise enough. Filtering itself is working, but you do not get the right filter values according to your custom query:

As you can see, you have 2 items in the list view, but all the filter values from the configured view.

So filtering is disabled – for now.

In my next blog, I show you an approach, how you can get filtering working as well.

 

You can download the Visual Studio 2010 Solution for the WebPart here

About these ads
This entry was posted in SharePoint Foundation, SharePoint Server 2010. Bookmark the permalink.

3 Responses to Using the XsltListViewWebPart with a Custom Query

  1. rammarappan says:

    Great Solution!..
    Is it possible to fix the filtering issue?

  2. Hi,

    i downloaded your solution and tried to implement it in my environment

    the issue i am facing is that the Event handler is not firing the code written in the
    void xsltWebpart_databinding function.. it is not hitting the code in side it. i even kept teh break point while debugging but it didnt clicked.. can you let me know any thing i have missed or any setting with the XSLT webpart.

    Would appreciate any pointers.
    Thanks
    Abhinav

    • Benedikt says:

      Hi Abhinav,
      did you ensure that the LVQueryWP.webpart is added as the first webpart to your page?
      It must be the first webpart in the WebPartManager.WebParts collection.
      (if not, the event is’nt fired).

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s