How to hide SharePoint list item columns

There are situations when you have to hide certain columns from customers' eyes. Today I am going to show one way to do that.

Let's go!

When its time to display item on a form, SharePoint takes the following actions:

  • looks into list schema to determine what custom template to use by looking at the "Template" attribute in Forms\Form element.
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" Template="MyCustomForm" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" Template="MyCustomForm" WebPartZoneID="Main" />
    </Forms>
  • or it looks into list schema to determine item's content type to look into for FormTemplates element in content type schema to find what control template to use to display the item for a given mode. For example, here is the exert  from default list schema and Item content type
     <XmlDocuments>
             <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
                          <FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
                                      <Display>ListForm</Display>
                                      <Edit>ListForm</Edit>
                                      <New>ListForm</New>
                          </FormTemplates>
                </XmlDocument>
    </XmlDocuments>
  • opens Program files\common files\microsoft shared\web server extensions\12\template\controltemplates and looks for control template's aspx file
  • if the control template is not defined by either way,  SharePoint uses default control templates from DefaultTemplates.ascx

This gives us the ability to provide our own template that will dictate to SharePoint how to display the list item. Lets look at the default ListForm control template for Item content type:

<SharePoint:RenderingTemplate ID="ListForm" runat="server">
    <Template>
        <SPAN id='part1'>
            <SharePoint:InformationBar runat="server"/>
            <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator="&nbsp;" runat="server">
                    <Template_RightButtons>
                        <SharePoint:NextPageButton runat="server"/>
                        <SharePoint:SaveButton runat="server"/>
                        <SharePoint:GoBackButton runat="server"/>
                    </Template_RightButtons>
            </wssuc:ToolBar>
            <SharePoint:FormToolBar runat="server"/>
            <TABLE class="ms-formtable" style="margin-top: 8px;" border=0 cellpadding=0 cellspacing=0 width=100%>
            <SharePoint:ChangeContentType runat="server"/>
            <SharePoint:FolderFormFields runat="server"/>
            <SharePoint:ListFieldIterator runat="server"/>
            <SharePoint:ApprovalStatus runat="server"/>
            <SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/>
            </TABLE>
            <table cellpadding=0 cellspacing=0 width=100%><tr><td class="ms-formline"><IMG SRC="/_layouts/images/blank.gif" width=1 height=1 alt=""></td></tr></table>
            <TABLE cellpadding=0 cellspacing=0 width=100% style="padding-top: 7px"><tr><td width=100%>
            <SharePoint:ItemHiddenVersion runat="server"/>
            <SharePoint:ParentInformationField runat="server"/>
            <SharePoint:InitContentType runat="server"/>
            <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator="&nbsp;" runat="server">
                    <Template_Buttons>
                        <SharePoint:CreatedModifiedInfo runat="server"/>
                    </Template_Buttons>
                    <Template_RightButtons>
                        <SharePoint:SaveButton runat="server"/>
                        <SharePoint:GoBackButton runat="server"/>
                    </Template_RightButtons>
            </wssuc:ToolBar>
            </td></tr></TABLE>
        </SPAN>
        <SharePoint:AttachmentUpload runat="server"/>
    </Template>
</SharePoint:RenderingTemplate>

In the above xml markup please note the undelined element which represents type Microsoft.SharePoint.WebControls.ListFieldIterator. This is the class that renders the fields on the form page and the SDK sports this exhaustive description for the type:

Renders each field in a list item, with some possible exceptions.

Well, it really iterates trough the collection of fields and [according to Reflector's output] generates required HTML according to field type and current control mode. For example, textual field is being rendered as a text box in "edit" and "new" mode and as a plain text label when in "display" mode.

The ListFieldIterator class has an overridable method IsFieldExcluded. If the method returns true, the field is not rendered at all.

Got an idea? Yes, we just override this method and use business  logic  to decide whether  to render field  or hide it completely from the user.

As a summary, here are the steps required to make the whole coulmn hiding thing work:

  1. Use (copy and paste) the original  ListForm rendering template from as a (duh!) template and save it to, for example, as FilteringListForm.aspx along with @Control, @Assembly and @Register directives to the controltemplates  folder in the 12 hive.
  2. Change the id of the template
    <SharePoint:RenderingTemplate ID="FilteringListForm" runat="server">
  3. In the customized template, replace SharePoint:ListFieldIterator element with class name of your own implementation of the Microsoft.SharePoint.WebControls.ListFieldIterator type.
  4. Create a class that inherits from ListFieldIterator class and override the method IsFieldExcluded.
  5. Apply your business rules in overriden method IsFieldExcluded.
  6. Reference the the new control template in either the Forms section of your list schema or in the  XmlDocuments node if you are customizing content type.

Enjoy!