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

 

Comments -
  1. Gravatar
    ssa

    Nice

      
  2. Gravatar

    I can't wait to try this. I've been trying to do it for a looonnng time.
    I once met a SharePoint MVP at a conference and he stated that "anything you can do through the GUI, you can do through the Object Model". When I asked him how to change the toolbar through the OM, he thought for a while and said "almost anything you can do through the GUI..."

      
  3. Gravatar

    I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

    Susan

    http://8080proxy.com

      
  4. Gravatar
  5. Gravatar

    Hi nsevens,


    Thanks for you reply. However these blogs do not do exactly what I needed for my project.


    The first solution would mean adjusting the view in the list definition and thus also adjusting the view if you are opening it from the list, not only if you are using it to show the list in a web part.


    The second solution misses the (after the infrastructure update) essential line:


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


    Thanks,


    Mirjam

      
  6. Gravatar

    Nice article.

    I also wrote a piece on this recenty:
    sharepointstudio.com/.../Post.aspx

    Mark

      
  7. Gravatar

    Good that you wrote it down, I just needed this info again, and also forgot about it.

      
  8. Gravatar

    This blog post explains it in detail:

    jasear.wordpress.com/.../listviewwebpart-progra...

      
  9. Gravatar
    AK

    Thank you Soo much........ I did this is SharePoint 2010. I added the above code in a new method. Once web parts were added and page was checked in. Then Call this method.

      
Comments have been closed on this topic.