Tuesday, February 16, 2010

Programatically modifying ListView Webparts

Scenario:
I was working on a small POC item, on how to update the listview webparts toolbar and fields after they have been added to the page.

Solution:
Here's the console application I used to test the concept. You might need to move this code as a Application Page Code behind or may be as a Feature Receiver code

Code:

using System;
using System.Reflection;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace SKN
{
class Program
{
static void Main(string[] args)
{
//This will be text for the link displayed in Summary toolbar for the webparts
string linkText = "Add a new item";

SPSecurity.RunWithElevatedPrivileges(delegate()
{
// get the site in this context
using (SPSite SiteCollection = new SPSite("http://ws2003/sitedirectory/try1"))
{
// get the web in this context
SPWeb myWeb = SiteCollection.RootWeb;

myWeb.AllowUnsafeUpdates = true;

SPLimitedWebPartManager mgr = null;
mgr = myWeb.GetLimitedWebPartManager("default.aspx", System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);

foreach (WebPart myWebPart in mgr.WebParts)
{
// Check if the webpart is a listview webpart
if (myWebPart.GetType().ToString().EndsWith("ListViewWebPart"))
{
//Convert the webpart to list view webpart type
ListViewWebPart listWebPart = (ListViewWebPart)myWebPart;

if (listWebPart != null)
{
//Get the list instance
SPList list = myWeb.Lists[new Guid(listWebPart.ListName)];
//Get the view details which is applied to webpart
SPView webpartView = list.Views[new Guid(listWebPart.ViewGuid)];

//Call the EnsureFullBlownXMLDocument for the view
webpartView.GetType().InvokeMember("EnsureFullBlownXmlDocument",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod,
null, webpartView, null);

PropertyInfo nodeProp = webpartView.GetType().GetProperty("Node",
BindingFlags.NonPublic | BindingFlags.Instance);
XmlNode node = nodeProp.GetValue(webpartView, null) as XmlNode;

// Get the handle for the toolbar node
XmlNode toolbarNode = node.SelectSingleNode("Toolbar");
if (toolbarNode != null)
{
toolbarNode.Attributes["Type"].Value = "FreeForm";
XmlAttribute positionNode = toolbarNode.OwnerDocument.CreateAttribute("Position");
positionNode.Value = "After";
toolbarNode.Attributes.Append(positionNode);
toolbarNode.InnerXml = @"<IfHasRights><RightsChoices><RightsGroup PermAddListItems=""required"" /></RightsChoices><Then><HTML><![CDATA[ <table width=100% cellpadding=0 cellspacing=0 border=0 > <tr> <td colspan=""2"" class=""ms-partline""><IMG src=""/_layouts/images/blank.gif"" width=1 height=1 alt=""""></td> </tr> <tr> <td class=""ms-addnew"" style=""padding-bottom: 3px""> <img src=""/_layouts/images/rect.gif"" alt="""">&nbsp;<a class=""ms-addnew"" ID=""idAddNewItem"" href=""]]></HTML><URL Cmd=""New"" /><HTML><![CDATA["" ONCLICK=""javascript:NewItem(']]></HTML><URL Cmd=""New"" /><HTML><![CDATA[', true);javascript:return false;"" target=""_self"">]]></HTML><HTML>" + linkText +@"</HTML><HTML><![CDATA[</a> </td> </tr> <tr><td><IMG src=""/_layouts/images/blank.gif"" width=1 height=5 alt=""""></td></tr> </table>]]></HTML></Then></IfHasRights>";
}

// Get the handle to the ViewFields ( in case you want to change the columns to be displayed )
XmlNode viewFieldsNode = node.SelectSingleNode("ViewFields");
if (viewFieldsNode != null)
{
viewFieldsNode.InnerXml = @"<FieldRef Name='LinkTitle' /><FieldRef Name='Attachments' />";
}

// Update the view
webpartView.Update();
}

}
}
myWeb.AllowUnsafeUpdates = false;
}
});
}
}
}
Enjoy :)

2 comments:

Unknown March 9, 2010 at 10:56 PM  

Do you not have to dispose off SPWeb at SPWeb myWeb = SiteCollection.OpenWeb();?

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.aspx

Sandeep March 10, 2010 at 1:03 AM  

Changed to RootWeb .. now I need not to dispose