Programmatically adjusting the toolbar of a ListViewWebPart

 

I have been doing more work on programmatically adding lists, views and ListViewWebParts to automatically created sites this week and I've stumbled onto another challenge that took me more time than I expected to solve.

 

I'm creating sites and pogrammaticaly adding ListViewWebParts to the default.aspx page of that site. By default a ListViewWebPart that is added to a page shows the Full Toolbar. This isn't always what you want. Even worse, it's usually not what you want.

If you add a ListViewWebPart to a page through the UI you can click Modify Shared Web Part and choose which toolbar type you want to use in the toolpart of the web part:

  • Full Toolbar
  • Summary Toolbar
  • No Toolbar

Unfortunately the object model doesn't have a property that lets you set the toolbar type. The SPView object does have a ToolbarType property, but this is read-only. I'm of course not the first person to run into this problem and there are a couple of blog posts out there that propose a solution to this problem. Unfortunately most of them don't work anymore after the infrastructure update. Ton Stegeman wrote a great post where he shares the code that lets you change the toolbar type if you have installed the infrastructure update. (http://www.tonstegeman.com/Blog/Lists/Posts/Post.aspx?List=70640fe5-28d9-464f-b1c9-91e07c8f7e47&ID=90) Ton's post shows how to set the toolbar type to None (which is the same as selecting No Toolbar" in the UI. In my case the type of toolbar depends on the web part. There are web parts that shouldn't have a toolbar at all, but there are also web parts that should have a summary toolbar. Of course if there are web parts that need a full toolbar you can just leave them as they are, as they get a full toolbar by default when they are added to the page.

 

Oh and be aware that taking shortcuts doesn't really help in this case.

I tried to change the toolbar right when adding the web part, but that didn't work too well. You should really add the web part first and then loop through the web parts on the page to change them.

Same thing is true for the views. I tried to adjust the view that I use when adding the web part, instead of getting the view from the web part that is already on the page. Doesn't work either. You need to get the view of the web part by using reflection and adjust that view to get this working. Otherwise you'll adjust the view of the list.( You can use this on April Fool's Day…set the toolbar of the views of your list to none. Users will go into the list and won't be able to see the toolbar and add items, even if they have full control.)

 

This is the code I used (again, courtesy to Ton, without his post I might still be looking for the solution).

 

SPLimitedWebPartManager wpManager = newWeb.GetLimitedWebPartManager("pages/default.aspx", PersonalizationScope.Shared);

 

// Get all web parts that are available on the default.aspx page

SPLimitedWebPartCollection webParts = wpManager.WebParts;

// Loop through the collection of all web parts on the page

foreach (System.Web.UI.WebControls.WebParts.WebPart webPartOnPage in webParts)

{

// Only try to set the toolbar type is the web part is a ListViewWebPart, other web part types don't have toolbars

if (webPartOnPage.GetType().Name == "ListViewWebPart")

{

ListViewWebPart listViewWebPart = webPartOnPage as ListViewWebPart;

 

// Get the view used in the web part by using reflection

PropertyInfo viewProp = listViewWebPart.GetType().GetProperty("View", BindingFlags.NonPublic | BindingFlags.Instance);

SPView webPartView = viewProp.GetValue(listViewWebPart, null) as SPView;

 

// This is necessary after the infrastructure update, without it you can't get to the XML of the view

webPartView.GetType().InvokeMember("EnsureFullBlownXmlDocument", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, webPartView, null, System.Globalization.CultureInfo.CurrentCulture);

 

PropertyInfo nodeProp = webPartView.GetType().GetProperty("Node", BindingFlags.NonPublic | BindingFlags.Instance);

XmlNode node = nodeProp.GetValue(webPartView, null) as XmlNode;

// Get the toolbar node from the XML of the view used in the web part

XmlNode toolbarNode = node.SelectSingleNode("Toolbar");

 

// Different action is needed depending on the web part

switch (webPartOnPage.Title)

{

case "Project Announcements":

 

if (toolbarNode != null)

{

// Set toolbar type to Summary Toolbar

toolbarNode.Attributes["Type"].Value = "Freeform";

 

XmlAttribute positionNode = toolbarNode.OwnerDocument.CreateAttribute("Position");

positionNode.Value = "After";

toolbarNode.Attributes.Append(positionNode);

 

// Add the CAML

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>Add new announcement</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>";

 

webPartView.Update();

}

break;

 

case "Project Tasks":

 

if (toolbarNode != null)

{

// Set toolbar type to No Toolbar

toolbarNode.Attributes["Type"].Value = "None";

webPartView.Update();

}

break;

case "Calendar":

 

if (toolbarNode != null)

{

// Set toolbar type to Summary Toolbar

toolbarNode.Attributes["Type"].Value = "Freeform";

 

XmlAttribute positionNode = toolbarNode.OwnerDocument.CreateAttribute("Position");

positionNode.Value = "After";

toolbarNode.Attributes.Append(positionNode);

 

// Add the CAML

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>Add new event</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>";

 

webPartView.Update();

}

break;

}//Switch

}//if ListViewWebPart

}//foreach webpart