I know what you are thinking, another article on how to change the toolbar on a SharePoint ListViewWebPart. Well I have to say, I have tried every method documented on the web and none of them work consistantly for me. I thought I was doing something wrong until I read all the comments and I was but one of many having similar results. Most of the articles go down the path of grabbing the view XML from the ListViewWebPart and modifing the toolbar type attribute which I have found to only exist about 25% of the time.
My method takes a different approach. I started my journey by looking at the ListViewWebPart code directly in Reflector, because it obviously needs to know how to do this because that's where the user changes it from the web site. From there I looked at "ListViewWebPart.GetToolParts" method which is the method SharePoint calls to get additional web part setting controls from the web part. In the case of the ListViewWebPart it returned a ListViewToolPart. The ListViewToolPart had a method called "ApplyChanges", this looks promising. Damn, obfuscated. No worry I can decipher IL for the most part. Bingo, there was the call I was looking for "ApplyViewToListWebPart". It took all the parameters I would expect, a reference to the ListViewWebPart and a toolbar type.
Here is the resulting code to wrap all the reflection nasty bits...
public static class ListViewWebPartHelper {
public static void SetToolbarType(
this ListViewWebPart lvwp,
SPLimitedWebPartManager limitedWebPartManager,
ListViewWebPartToolbarType type) {
#pragma warning disable 618
string storageKey = lvwp.StorageKey.ToString("B").ToUpper();
string listId = lvwp.ListName;
string viewId = lvwp.ViewGuid;
uint toolbarType = (uint)type;
// get the SPWebPartManager from SPLimitedWebPartManager
PropertyInfo webPartManagerProp = typeof(SPLimitedWebPartManager).GetProperty(
"WebPartManager",
BindingFlags.NonPublic | BindingFlags.Instance);
SPWebPartManager webPartManager = (SPWebPartManager)webPartManagerProp.GetValue(limitedWebPartManager, null);
// get the SPWebPartConnection from SPWebPartManager
PropertyInfo spWebPartsProp = typeof(SPWebPartManager).GetProperty(
"SPWebParts",
BindingFlags.NonPublic | BindingFlags.Instance);
SPWebPartCollection webParts = (SPWebPartCollection)spWebPartsProp.GetValue(webPartManager, null);
// Call the ApplyViewToListWebPart method on the SPWebPartConnection
// internal void ApplyViewToListWebPart(
// string storageKey,
// string listID,
// string viewID,
// uint toolbarType,
// out uint flags)
MethodInfo applyViewToListWebPart = typeof(SPWebPartCollection).GetMethod(
"ApplyViewToListWebPart",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[]{
typeof(string),
typeof(string),
typeof(string),
typeof(uint),
typeof(uint).MakeByRefType()
},
null);
object[] parameters = new object[5];
parameters[0] = storageKey;
parameters[1] = listId;
parameters[2] = viewId;
parameters[3] = toolbarType;
applyViewToListWebPart.Invoke(webParts, parameters);
#pragma warning restore 618
}
}
public enum ListViewWebPartToolbarType {
Full = 0,
Summary = 1,
NoToolbar = 2
}
And here is how to use the code...
SPFile homePage = _ctx.Site.Files["default.aspx"]; SPLimitedWebPartManager limitedWebPartManager = homePage.GetLimitedWebPartManager(PersonalizationScope.Shared); ListViewWebPart webPart = (ListViewWebPart)limitedWebPartManager.WebParts[0]; webPart.SetToolbarType(limitedWebPartManager, ListViewWebPartToolbarType.NoToolbar); limitedWebPartManager.SaveChanges(webPart);
And here is my rant to Microsoft that each and everyone of these articles about this issue must include... Really, Microsoft did you not think that people would want to do this. You have had 2 service packs come out for SharePoint and you couldn't have fixed this yet. Please fix this in SharePoint 2010.
11 Comments
Leave a comment
0 TrackBacks
Listed below are links to blogs that reference this entry: Changing the toolbar on a SharePoint ListViewWebPart.
TrackBack URL for this entry: http://www.nearinfinity.com/mt/mt-tb.cgi/619



Hi Joe,
I'm glad to have found your blog entry. It seems to be very promising after having tried all the code spread around the web and always looking at that toolbar not showing a bit of a sign wanting to disappear. So I want to try out your code but something is wrong with it (or me, which I hope).
I am using VS2008 with MOSS 2007 on W2K8-Server and implemented your code. After WSPbuilding and deploying I receive an error calling the page with the toolbar I want to have disappeared. The error states CS1031: Type expected when reaching
MethodInfo applyViewToListWebPart = typeof(SPWebPartCollection).GetMethod("ApplyViewToListWebPart", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string), typeof(string), typeof(string), typeof(uint), typeof(uint).MakeByRefType() }, null);
So, as I am a VB developer and new to C# it may have happened that I did something wrong. But I don't get around with it. Perhaps you can help.
Thanks a lot
Michael
CS1031 sounds like a compiler error not a runtime error. You could be missing a "using" statement. Could you give more information on where you put this code? It's best placed in a feature receiver or some place that you are adding the webparts manually to the page.
Hi Joe,
I'm glad to see others having the same problem. Hope, Microsoft will hear the crying!
I implemented your code in my project but as I am new to c# (did only VB now) I hit a problem with
MethodInfo applyViewToListWebPart = typeof(SPWebPartCollection).GetMethod("ApplyViewToListWebPart", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(string), typeof(string), typeof(string), typeof(uint), typeof(uint).MakeByRefType() }, null);
which gives an error CS1031: Type expected.
I looked for information about reflection and I think I understand the principle. But I do not have any idea how to solve that problem. So if you have any time for me, please help.
Thanks
Michael
Ah, I think I figured it out. You are probably not using the latest C# compiler. Try this...
MethodInfo applyViewToListWebPart = typeof(SPWebPartCollection).GetMethod(
"ApplyViewToListWebPart",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[]{ typeof(string), typeof(string), typeof(string), typeof(uint), typeof(uint).MakeByRefType() },
null);
In older C# compilers you need to specify the type when creating an array "new Type[]...". In the new C# compiler it's implicit.
Hello Joe,
YES! YES! YES!
that was it. AND: your code IS WORKING! Thank you for your support. Have a nice day.
Michael
Life saver, I really didn't want to have to muck around with the Xml for the view. Worked first time without any issues.
Thanks
Simon
YES YES YES again.
Thank you.
I can't thank you enough for this post! I've been working on this for a couple of days and have been facing other provisioning tasks that this approach could prove very useful for. Thanks again!
Hi Joe! This looks like it will do what I want, but I don't understand the bit of code in the "how to use" box. Where is _ctx defined, and how does "webpart" get the SetToolBarType method?
Thanks,
-Jay
Big help, thanks!
Do you know why it fails on
applyViewToListWebPart.Invoke(webParts, parameters);
wtih:
====
The system cannot find the file specified. (Exception from HRESULT: 0x80070002) at Microsoft.SharePoint.SPWebPartCollection.ApplyViewToListWebPart(String storageKey, String listID, String viewID, UInt32 toolbarType, UInt32& flags)
===