If you have ever tried adding a SharePoint custom action to the actions menu and tried using "List" or "ContentType" as the "RegistrationType" and then tried to specify a specific list or content type in the "RegistrationId" you know that it doesn't work. SharePoint will silently not render your custom action. If you try and target a generic list using a "RegistrationId" of "100" you will see that SharePoint will gladly render your action on every list in the site. I have found a rather kludgy work around to the problem.
First off in your element manifest file you need to use the "ControlAssembly" and "ControlClass" attributes off of CustomAction. MSDN doesn't say a whole lot about these attributes but essentially they allow you to specify a web control class in your assembly which can render the action. (If you need to create hierarchical menus check out this article.) Here is the XML to get you started:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="MyCustomAction"
RegistrationType="List"
GroupId="ActionsMenu"
Location="Microsoft.SharePoint.StandardMenu"
Sequence="1000"
ControlAssembly="[Fully qualified assembly name]"
ControlClass="MyNamespace.MyCustomAction">
</CustomAction>
</Elements>
Next you will need to create a web control class which renders the menu item, as seen below:
public class MyCustomAction : WebControl {
private MenuItemTemplate _action;
protected override void CreateChildControls() {
SPWeb site = SPContext.Current.Web;
_action = new MenuItemTemplate {
Text = "My Action",
Description = "My Action",
ImageUrl = "/_layouts/images/NEWITEM.GIF",
ClientOnClickNavigateUrl = "http://www.nearinfinity.com"
};
Controls.Add(_action);
}
}
Compile and deploy your solution. Oh and make sure to add your assembly and namespace to the safe control list or you will end up pulling your hair out because once again SharePoint will silently not render your menu item. You should now see the "My Action" on every list in the site. We have now reproduced what a standard CustomAction element in your element manifest would do normally. Now we need to find a way to determine which list our control is being added to. The best way I found for doing that is to traverse the control hierarchy up the parent chain until I found the containing ListViewWebPart. The code is quite simple and looks like this:
private ListViewWebPart GetParentListViewWebPart() {
Control parent = Parent;
while (parent != null) {
if (parent is ListViewWebPart) {
return (ListViewWebPart)parent;
}
parent = parent.Parent;
}
return null;
}
You should know where I'm going with this now, but for completness I will show you the last piece of code below which restricts it to a single list instance:
private Guid TARGET_LIST_ID = new Guid ("0D9B9302-8599-4CE5-8695-1B95FE7378F1");
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
if (!Page.IsPostBack) {
EnsureChildControls();
_action.Visible = false;
ListViewWebPart listView = GetParentListViewWebPart();
if (listView != null) {
Guid listGuid = new Guid(listView.ListName);
if (TARGET_LIST_ID == listGuid) {
_action.Visible = true;
}
}
}
}
Now that we have the list Guid that our control is being rendered for I will leave it as an exercise to the reader to restrict it to a given content type.
Why SharePoint doesn't provide this kind of functionality out of the box amazes me, but at least they provide a powerful API that you can get in there and work around it in a not so horribly kludgy way. Maybe SharePoint 2010 will include this :)
13 Comments
Leave a comment
0 TrackBacks
Listed below are links to blogs that reference this entry: How to add a custom action to a SharePoint list actions menu for a specific list or content type..
TrackBack URL for this entry: http://www.nearinfinity.com/mt/mt-tb.cgi/611



Do you know how to determine the ListItemID of the Item on which the Custom Action was selected?
Or much easy is to do this:
SPWeb web = SPContext.Current.Web;
SPList list = SPContext.Current.List;
Voila ! you have the web and the current list :)
Nice one. :)
Hello,
Once I deployed the solution, it worked excellent on my list, but it have generate problem on other ones, other list just dont open anymore, I just comment the code inside onLoad() and now the other pages work fine, but again I have the menu item showing in all lists, Have you had this problem? let me know if you want me to send you the exact error, thanks
I haven't run across that problem. I would love to see the error you are seeing.
I do not know how to get the ListItemID. I'm adding the menu item to the "Actions" menu not the list item's ECB menu.
Hey Guys,
I completely agree with this approach. My Question is some thing else .... Can we get a similar item in the (custom action) in the ECB or Toolbar in sitemanager.aspx in Layouts folder ? If you have any idea please revert back to be ;-)
Regards
Amith Sasi
Hi Joe, Sorry this will be a newbie question. But this is exactly what i need to do. Create a custom menu item for a specific list. the only thing is im not a developer. I found some steps on how to make a feature menu item to be displayed through out the whole site. but since im not that advanced i dont know what to do with the last two sections of code you provide. when you wrote "traverse the control hierarchy up the parent chain " and "you should know where im going with this". i felt left out :( J/K) but is there anyplace you can point me to a step by step where to place the extra code you provided to make this happen? any help would be greatly appreciated. thanks
The ECB is rendered from JavaScript.
To know what item an action has been triggered on include "{ItemId}" as a param in your URLAction.
I want add three new CustomAction in ECB for a specific list.I do this for one custom action with install and activate feature with RegistrationId=Content Type Id.but I want three custom action not one.
My question is this:can i add some custom action in ECB for one specific list with this method?
"of vital importance"
please Help me....!!!
@Joe - Thanks for sharing.
@Lara - check if this helps
http://msdn.microsoft.com/en-us/library/ms473643(lightweight).aspx
Add three actions with diff id's in the manifest.xml
When you said compile and deploy your solution, you have to have the feature file right? Can you explain to me what you ment exactly about Compile and deploy? because i did not understood thanks
I am trying use this concept ECB menu, But I just see a blank menu. When I click on it, it says invalid Url. Anybody is having the same issue.