Control the Content Types in the New menu via code

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…

list-schema

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.

not-shown-on-new-menu

shown-in-content-type-drop-down

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")
{
ctList.Remove(ct);
break;
}
}
rootFolder.UniqueContentTypeOrder = ctList;
rootFolder.Update();

//Add the content type back
IList<SPContentType> ctList2 = rootFolder.ContentTypeOrder;
ctList2.Add(docs.ContentTypes["MyDocumentContentType"]);
rootFolder.UniqueContentTypeOrder = ctList2;
rootFolder.Update();
}
}

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.

Control the Content Types in the New menu via code

9 thoughts on “Control the Content Types in the New menu via code

  1. gaurav kanwar says:

    Hi,
    When the Site on which the content is hidden as shown above , I tried to move that
    site with in site collection, hidden content types become visible agin on the moved
    site. Is this a bug in sharepoint or I need to re exectue the code agin when the site
    is moved from one place to another

    Thanks in advance

  2. No idea, to be honest. What happens with content types that you hid through the user interface? Do they behave in the same way?

  3. Anna says:

    “in my Schema.xml for my custom Document library I can specify Hidden=”TRUE” in the ContentType node”

    Where can I find this schema.xml? I have created my content type with the visual interface. Where can you see the xml or the code?

    Thanks

  4. Well, through the SharePoint User Interface, you can’t. If you’re just configuring a system – rather than creating a solution to roll out across multiple site collections – then you can disable the content type from the document library settings.

    Go to Document Library Settings > Advanced Settings > Allow management of content types.

    Then go to Document Library Settings > Change New Button Order and Default Content Type. Uncheck the checkbox for the content type you want to hide.

    The article above is more for solution developers who’re building a feature to deploy a document library.

  5. Anna says:

    Hello again,

    I followed the above instructions and the Content Type was removed from the New button. But it also removed from the Upload. Is this correct, or there is a trick to have it only in the upload.

    Thanks

  6. Kathy says:

    Hi Andy,

    I want to set the uniquecontenttypeorder at folder level, when a new folder is created in my doc Lib. I have the following code in my custom itemAdded Event

    SPListItem listItem = properties.ListItem; // SPItemEventProperties properties
    SPContentTypeCollection contentTypeCollection = listItem.ParentList.ContentTypes;

    System.Collections.Generic.IList order = new System.Collections.Generic.List();

    SPContentType ct1 = contentTypeCollection[” My Content Type1″];
    if (ct1 != null)
    order.Add(ct1);

    SPContentType ct2 = contentTypeCollection[” My Content Type2″];
    if (ct2!= null)
    order.Add(ct2);

    SPFolder folder = listItem.Folder;
    folder.UniqueContentTypeOrder = order;
    folder.Update();

    The code above works if I only add ct1 and then set the UniqueContentTypeOrder of folder.

    When I add ct2 to Order and then set the UniqueContentTypeOrder of folder I get an ArgumentOutOfRangeException thrown from the set_UniqueContenttypeOrder setter function.

    Any help appreciated.

    Thanks.

  7. Hmm. I’m not sure. I’d try setting ‘order’ to be at list of IList. But yes, I got lots of errors with adding SPContentTypes back into the list.

    Could you add them one at a time? Ugly, but might work!

Leave a reply to Anna Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.