XSLTListViewWebpart in Sharepoint 2010 Uncovered


Successor and much more powerful webpart than Dataform or ListViewWebpart provided in Sharepoint 2010, yes, that’s true.

As mentioned in msdn, it handles view rendering for lists which can be document libraries as well as announcements. As the name suggests, it uses a XSLT i.e transforms for Html rendering. Xml data obtained as per Query and XmlDefinition, explained later, is converted into html using Xslt. It, by default, applies styles [ViewStyles] as provided by Sharepoint.

It provides an option to enable column filtering, sorting, Paging and AJAX as well. Yes, filtering, sorting, Paging can be done async, without whole page refresh using AJAX option.

What’s more? You can even define your own custom xsl defining styles, rendering and you have a data rendered the way you want. Custom xslt can override default templates and thus has a power to completely replace default XSLTs which is rarely needed.

For e.g. Dates to be shown in a particular format or you want to specify custom header names rather than display names defined in a list definition or a view.

Isn’t it powerful from what we had earlier?

Why am i writing this?

In my project, i had a requirement to show latest 5 documents with a More… button at the bottom in a page which had other data as well. It should support sorting, filtering but without paging. And most importantly, to show list data which exists in a different site collection.

Surely this is achievable by writing a custom visual web part and a backend code but how much time does this require? If you are following a layered approach and are following a well-defined architecture :), which you will be as a good coder, it can take a lot of time with a filtering, sorting support. And what if Client demands for Paging later. This usually happens in Agile methodology. Plus why to forget a testing?

This is where XsltListView webpart can be handy, inbuilt webpart, already test proven, just set few properties as per your requirements and you are good to go.

But…

What to set, when, why? If you want to use this webpart and you don’t have knowledge how to use it, I pray to God.

You have now 2 options:

  • Either spend a lot of time yourself, exploring this XsltListViewWebpart, or
  • Refer to this blog :). If not 100% , it will definitely save more than 75% of your efforts in fiddling around

How to use?

Following are the few properties which must be considered when using this webpart:

You can either make use of SharepoingDesigner (SPD) or your skill 🙂 to define XsltListViewWebPart definition declaratively.

This is how your final XsltListViewWebpart definition should look like in an ascx file. Just set properties as per your needs here or in the code behind.
Download Sample XSLTListViewWebPart Declaration


Few things to note in the above declaration:

  • Attributes set on element WebPartPages:XsltListViewWebPart like AutoRefresh, AsyncRefresh, AllowEdit, AllowConnect, AllowHide, SuppressWebPartChrome, UseSQLDataSourcePaging, Title, AllowMinimize, ListUrl

Note: ViewGuid attribute if is set when imported through SPD, remove it and set it from the code behind when sites hosting a list are provisioned programmatically.

Consider a below scenario.Each child site in this case then will have a different view identifier and when set wrongly, will raise an exception even without giving a clue, hard to debug. Believe me. My personal experience.

  • ParameterBindings are useful in sorting, filtering
  • XmlDefinition: This definition is the most important part. This defines :
  1.  a view element – Specifies which all fields should be shown on UI, their order through ViewFields element
  • RowLimit element whose value defines the page size. It has an optional attribute Paged which when set to true enables paging
  • Aggregations element which shows a checkbox in each row depending upon the value of mode attribute
  • ViewStyle element whose ID attribute tells which default style should be applied
  • Toolbar element whose Type attribute when set to None doesn’t show any Add button at the bottom
  • Query element which is useful in defining a default column sorting and filtering

Note: In declaration: FieldRef Name=””  , FieldName should be the static name defined while creating a list. If this doesn’t match, an exception is raised.

  • Xsl element defines templates which can override default templates. You can also provice XslLink rather than defining whole Xsl here.

In the above code, defined template does the custom formatting of DateTime. Have a look at mode attribute value. For all DateTime fields which need custom formatting should have value set as DateTime_body. While applying Xslt, this template will be invoked as per the match attribute value.

For the above definition, template will be invoked for a field\column named PromotionDate. It’s value will be shown in ‘dd MMM yyyy’ format.

How to set WebId, ListId, ViewGuid from code?


using (SPSite rootSiteCollection = new SPSite("SiteUrlGoesHere"))
{
using (SPWeb web = rootSiteCollection.OpenWeb())
{
this.ListModuleDocuments.WebId = web.ID;
moduleDocumentLibrary = web.Lists.TryGetList("DocumentLibraryName");
if (moduleDocumentLibrary == null)
{
Logger.LogError("ErrorMessage");
}
this.ListModuleDocuments.ListId = moduleDocumentLibrary.ID;
this.ListModuleDocuments.ListName = moduleDocumentLibrary.ID.ToString();
this.ListModuleDocuments.ViewGuid = moduleDocumentLibrary.DefaultView.ID.ToString();
}
}

Scenario 1: XsltListViewWebpart reads data from list in a different site\site collection

If this is your requirement and you follow the above steps without setting Toolbar’s RenderContext, you will see a non-informative, wrong exception details on a browser.

What to do now?

Copy n Paste:) Yes, copy the below code, call this code after setting various identifiers.


///
/// Sets the context of Toolbar of XsltListView webpart
/// Module web which has the document library
private void SetToolbarContext(SPWeb web)
{
try
{
// Get hold of the toolbar that renders the new menu items
ViewToolBar toolBar = this.GetPrivatePropertyValue("ToolbarControl");
if (toolBar == null)
{
return;
}
// Create the SPContext object that references the correct SPList, SPView and most importantly..SPWeb
SPContext context = SPContext.GetContext(HttpContext.Current, new Guid(this.ListModuleDocuments.ViewGuid), this.ListModuleDocuments.ListId, web);
// Set the RenderContext of the ToolbarControl
toolBar.RenderContext = context;
}
catch
{
}
}

///
/// Gets the toolbar property
/// A Toolbar of type
/// name of the property
/// Toolbar of type
private T GetPrivatePropertyValue(string name)
{
PropertyInfo propertyInfo = this.ListModuleDocuments.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (propertyInfo == null)
{
throw new ArgumentOutOfRangeException("name", string.Format(CultureInfo.InvariantCulture, "Property {0} was not found in Type {1}", name, this.ListModuleDocuments.GetType().FullName));
}
return (T)propertyInfo.GetValue(this.ListModuleDocuments, null);
}
// Here, ListModuleDocuments is a XsltListViewWebpart ID( reference name)

Building Query in XmlDefinition

Query element defines a CAML query. You can specify all filter criterias, sorting on required columns in a way much similar to sql constructs. It supports the logical operations as well.

If you see, this Query is nothing but a structured XML tree which when built can do data selection, data ordering and grouping within a small time, not requiring a great effort or undestanding.

You can learn more on this msdn article
to understand which all operators are supported. A very nice and explanatory article.

Is Custom Filtering supported?

An answer to this is definitely Yes. Let’s talk about the following scenario:

Page has two data sections (webparts): DWP1 and DWP2. DWP1 shows a tabular data for Task entity which has a TaskName column. DWP2 shows all documents of a document library DL1 by default. This DL1 is a store for all Task entity documents. Thus, DWP1 and DWP2 are connected in a sense that each task row in DWP1 may have some docs in DL1 associated to it.

Another requirement reads, if a user clicks on any TaskName in DWP1, docs in DWP2 should be filtered as per the selected TaskName.

This can be done by setting up an InterConnection b/w the two web parts, i.e. defining InterConnected webparts or  have a custom javascript which does a postback on a TaskName click.

Postback is a necessary but not sufficient step.In a postback event handler, Filter query must be modified to fetch only that selected\clicked Task documents.

How to do this? Simple. Yeah simple as long as you know the way.

Modify Query element in XmlDefinition. XsltListViewWebpart exposes a read\write property named XmlDefinition of type System.String. If you read it intially, it will be same as what you would have declared in ascx file. Now, read the Query > Where element, if exists otherwise add a Where element fulfilling your filter criteria.

You can either read XmlDefinition in an XmlDocument and then do xpath query and manipulation or using String manipulation, change XmDefinition directly.

Do remember that you have to assign modified xml definition back to XmlDefinition property. There you go. XsltListViewWebpart will now handle everything for you and fetch only the required data. It has a good performance as well because it won’t fetch the complete data (all tasks’ documents ) and then apply a filter query. Instead, it is similar to reading the filtered data from MS SQL (store).

I struggled, people kept suggesting other techiniques but not this and i believe nothing can be simpler than this.

Where to find Sharepoint Default XSLTs?
Sharepoint 2010 default transforms files are placed in 14 hive, specifically @
%PROGRAMFILES%\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\XSL

Files to be peeked for understanding:

  • fldtypes.xsl
  • main.xsl
  • internal.xsl
  • vwstyles.xsl

Possible Errors and Exceptions

  • Specified view is invalid

Reason: ViewGuid is set in the declarative section of ascx file. This value doesn’t match with the actual view identifier of a list in that particular web.

Resolution: Remove this attribute and set it from the code behind

  • Value does not fall within the expected range

Reason: This is due to toolbar’s render context being set to current web and not to the web which has a list. Remember, XsltListViewWebpart can show data from a list contained in a different web.

Resolution: Set the Toolbar’s RenderContext as shown in the above code snippet.

References

Download Sample XSLTListViewWebPart Declaration

This article doesn’t tell what you want? Need help? Contact me.

Advertisements

27 thoughts on “XSLTListViewWebpart in Sharepoint 2010 Uncovered”

  1. I have followed all your steps still I am not able to add XSLTListViewWebpart in my custom user control . Can you please share the workfing code for more help ?

    Like

  2. Hi,

    nice article. Do finally understand a bit more about xsltlistviewwebparts.

    In your article you do have a section for “reading cross sitecollection”. I’ve been playing for months with it now and still am not able to get this working.

    Do you have any clue? If I use your code as an example, I never retrieve the “toolbarControl” object, it is always null and so, if I add the webpart (with webId, ViewGuid en ListId setup from the other sitecollection) I receive the error “specified view is invalid”).

    Any thoughts on that?

    Like

      1. Hi,

        I’m going to try again and if I get an exception I will let you know. Yesterday I received following exceptions: Invalid View and after a while, and modifying code, I received “Value does not fall within the expected range” 😦

        I have code it like this:

        using (SPSite site = new spsite(“http://sitecollectionA/”))
        {
        using (SPWeb web = site.openweb())
        {
        SPView view = GetTheList.MyView;
        XsltListViewWebPart.ViewGuid = view.ID;
        }
        }

        I will try again and eventually post a “full” working code, the above is a rough draft 🙂

        Like

      2. Hi,

        I’ve just tried it again with your uploaded code and added some codebehind in de ascx.cs file, inside the override oninit method:

        protected override void OnInit(EventArgs e)
        {
        base.OnInit(e);

        using (SPSite rootSiteCollection = new SPSite(“http://exs-localdev/msp”))
        {
        using (SPWeb web = rootSiteCollection.OpenWeb())
        {
        this.ListModuleDocuments.WebId = web.ID;
        SPList moduleDocumentLibrary = null;
        moduleDocumentLibrary = web.Lists.TryGetList(“ATLAS2_DOCUMENT_LIST”);
        if (moduleDocumentLibrary == null)
        {
        LOGGING.LoggingService.WriteTraceAndEvent(“Error nestUserControl”);
        }

        this.ListModuleDocuments.ListId = moduleDocumentLibrary.ID;
        this.ListModuleDocuments.ListName = moduleDocumentLibrary.ID.ToString();
        this.ListModuleDocuments.ViewGuid = moduleDocumentLibrary.DefaultView.ID.ToString();
        }
        }

        }

        When I run this, I don’t get an exception while debugging… but in the log files it’s telling me that it cannot find subsite /msp …. which is off course correct because /msp is inside another site collection…

        Any thoughts?

        Like

        1. Please do this. Go to your List from Sharepoint UI.
          From there copy a list url and then use that url while constructing a SPSite. after this when you will call Openweb(), handle to your web hosting that list will be available and then continue.
          Or you give me the list url.

          Like

          1. This is a long-shot as this post is almost 2 years old now, but I’m hitting the same (I believe) error that Dj_Vibri is. “There is no Web named ‘/sites/WEB_NAME'”. I believe this has something to do with the context and trying to use the webpart to display a cross-site collection list. It just doesn’t seem like it will work. Something internally to the webpart uses the current context. So it works cross-SITE (different sites in the same site collection), but not cross- SITE COLLECTION. If anyone has had any success getting a webpart to function cross-site collection, I would love more details.

            Full stack trace when trying to load this cross-site collection:
            System.IO.FileNotFoundException: There is no Web named “/sites/xxxxx”.
            at Microsoft.SharePoint.Library.SPRequestInternalClass.OpenWebInternal(String bstrUrl, Guid& pguidID, String& pbstrRequestAccessEmail, UInt32& pwebVersion, String& pbstrServerRelativeUrl, UInt32& pnLanguage, UInt32& pnLocale, String& pbstrDefaultTheme, String& pbstrDefaultThemeCSSUrl, String& pbstrThemedCssFolderUrl, String& pbstrAlternateCSSUrl, String& pbstrCustomizedCssFileList, String& pbstrCustomJSUrl, String& pbstrAlternateHeaderUrl, String& pbstrMasterUrl, String& pbstrCustomMasterUrl, String& pbstrSiteLogoUrl, String& pbstrSiteLogoDescription, Object& pvarUser, Boolean& pvarIsAuditor, Int32& plSiteFlags, Boolean& pbOverwriteMUICultures, Boolean& pbMUIEnabled, String& pbstrAlternateMUICultures, Int32& puiVersion, Int16& pnClientTag)
            at Microsoft.SharePoint.Library.SPRequest.OpenWebInternal(String bstrUrl, Guid& pguidID, String& pbstrRequestAccessEmail, UInt32& pwebVersion, String& pbstrServerRelativeUrl, UInt32& pnLanguage, UInt32& pnLocale, String& pbstrDefaultTheme, String& pbstrDefaultThemeCSSUrl, String& pbstrThemedCssFolderUrl, String& pbstrAlternateCSSUrl, String& pbstrCustomizedCssFileList, String& pbstrCustomJSUrl, String& pbstrAlternateHeaderUrl, String& pbstrMasterUrl, String& pbstrCustomMasterUrl, String& pbstrSiteLogoUrl, String& pbstrSiteLogoDescription, Object& pvarUser, Boolean& pvarIsAuditor, Int32& plSiteFlags, Boolean& pbOverwriteMUICultures, Boolean& pbMUIEnabled, String& pbstrAlternateMUICultures, Int32& puiVersion, Int16& pnClientTag)
            at Microsoft.SharePoint.SPWeb.InitWebPublic()
            at Microsoft.SharePoint.SPWeb.get_ID()
            at Microsoft.SharePoint.SPContext.DefaultKey(HttpContext context, SPWeb web)
            at Microsoft.SharePoint.SPContext.GetContext(HttpContext context, Guid viewId, Guid listId, SPWeb web)
            at Microsoft.SharePoint.WebPartPages.DataFormWebPart.CreateChildControls()
            at Microsoft.SharePoint.WebPartPages.BaseXsltListWebPart.CreateChildControls()
            at Microsoft.SharePoint.WebPartPages.WebPartMobileAdapter.CreateChildControls()
            at System.Web.UI.Control.EnsureChildControls()

            Like

      3. Hi there,

        thanks for the input. I’ve been to the list through the SP UI and retrieved following URL: http://exs-localdev/msp/ATLAS2_DOCUMENT_list/Forms/ATLAS2_DOCUMENT_view.aspx

        When I use this inside the SPSite constructor I keep receiving the following exception:
        System.IO.FileNotFoundException: Er is geen web met de naam /msp. (Translated: There is no web named /msp).
        What I’m trying to do is the following:
        – I have a list named “ATLAS2_Document_List” inside the site collection “http://exs-localdev/msp”
        – I have another site collection at “http://exs-localdev/sites/sps_N/5585” where I want to put this webpart on, so I can render an xslt webpart with items displayed from another sitecollection.

        Maybe I’m doing something wrong in code, or on the wrong place or something…

        Like

        1. Hi,
          Sorry for replying so late.
          Can you create a Console Application having the same code: SPSite and SPWeb object creation. Make sure to refer Microsoft.Sharepoint in your project and compile it using .NET framework other than 4.0. Try site.RootWeb instead of site.OpenWeb() as well.
          Can we sit together sometime, do live meeting and desktop sharing to get to the actual problem?

          Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

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

Google photo

You are commenting using your Google 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 )

Connecting to %s