We’ve got a project with an interesting requirement for a Document Library. When the site it provisioned, it will have a number of documents already in it, of a specific content type. Users should not be able to create more documents of that content type. Further, we would be uploading documents via some custom screens which should also be stored as ‘hidden’ document content types.
No problem, I thought – in my Schema.xml for my custom Document library I can specify Hidden=”TRUE” in the ContentType node. Sadly, this doesn’t work entirely well…
This removed the content type from the ‘New’ menu on the list’s toolbar – but not the ‘Content Type’ drop down list on the EditForm.aspx.
What the MSDN documentation actually says is:
Hidden : Optional Boolean. TRUE to define the content type as hidden. If you define a content type as hidden, Windows SharePoint Services does not display that content type on the New button in list views.
If you do not include this attribute, Windows SharePoint Services treats the content type as if this attributes was set to FALSE.
Okay… …so that’s the ‘why you’d want to do it’. Now how do I define what is in both the ‘New’ menu and the EditForm.aspx dropdown list?
Well, it’s a bit curious. This information is stored in the RootFolder of the list. The root folder has a couple of properties:
They are both lists of SPContentType objects, and define the items and order of item on the menu and drop down. Remove an object from the list, and it won’t appear on these controls.
So, what code does this?
using (SPSite site = new SPSite("http://vm-moss2007/"))
using (SPWeb web = site.OpenWeb())
SPList docs = web.Lists["MyList"];
SPFolder rootFolder = docs.RootFolder;
IList<SPContentType> ctList = rootFolder.ContentTypeOrder;
// Remove the content type
foreach (SPContentType ct in ctList)
if (ct.Name == "MyDocumentContentType")
rootFolder.UniqueContentTypeOrder = ctList;
//Add the content type back
IList<SPContentType> ctList2 = rootFolder.ContentTypeOrder;
rootFolder.UniqueContentTypeOrder = ctList2;
This code opens a web, opens a list, removes one of the content types, and then adds it back again. Seems to work nicely, and I’ve now built it into feature receiver so that when the list is created by my site definition, I programmatically remove some content types from the menus.
Edit: note that the code about uses the SPList.ContentTypes collection, not the SPWeb.ContentTypes collection to get the content type to add. If you use the SPWeb one, the set_UniqueContenttypeOrder setter function will throw an ArgumentOutOfRangeException.