Introduction


Assume you have a requirement for making fields on a list read only once an item is added (a write-once field). Using the UI (User Interface), this isn't possible.

There is a way to achieve a similar result though, by using PowerShell to edit the field (or by using CAML properties when declaring the field declaratively). This solution doesn't actually set the field for a list item as read only; it just removes the field from the UI so it can't be edited once it's set.

Applies To

  • SharePoint 2010
  • SharePoint 2013

The Desired Result


1. A user can add a new list item, and view all the fields.



2. A user can view the list, and see all the fields.



3. The user can edit the list item, but they can only edit a limited number of fields.



How the Solution Works


The solution works by setting boolean values that determine if the field is rendered in the new, view and edit forms. By setting the ShowInNewForm or ShowInEditForm property to false, the user has no way of editing the field (other than to use the DataGrid View, which can also be disabled).

The PowerShell Based Solution


The following PowerShell performs the following actions:
  • Removes the "Title", "Item", "Found By" and "DateItemFound" fields from the Edit Form, so that they can't be changed once a list item has been created. 
  • Removes the "AdministrativeNotes" field from the New Form.
  • Disables the DataGrid view
$web = Get-SPWeb "http://devmy131"            
$list = $web.Lists["Lost Property"]            
$field = $list.Fields["Title"]            
$field.ShowInEditForm = $false;            
$field.Update();            
$field = $list.Fields["Item"]            
$field.ShowInEditForm = $false;            
$field.Update();            
$field = $list.Fields["FoundBy"]            
$field.ShowInEditForm = $false;            
$field.Update();            
$field = $list.Fields["DateItemFound"]            
$field.ShowInEditForm = $false;            
$field.Update();            
$field = $list.Fields["AdministrativeNotes"]            
$field.ShowInNewForm = $false;            
$field.Update();            
$list.DisableGridEditing = $true;            
$list.Update();            
$web.Dispose();

The CAML Based Solution


The following CAML can be used in a List Definition (in the lists Schema.xml file) to set the same properties on the fields. 

<Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Type="Text" Name="Title" DisplayName="Title" Required="TRUE" StaticName="Title" ShowInEditForm="FALSE" />
 
<Field Type="Text" DisplayName="Item" Required="TRUE" ID="{940a19c1-1dd6-4035-9107-32d159d77623}" StaticName="Item" Name="Item" ShowInEditForm="FALSE"/>
 
<Field Type="User" DisplayName="FoundBy" List="UserInfo" Required="TRUE" ShowField="ImnName" UserSelectionMode="PeopleOnly" UserSelectionScope="0" ID="{56142494-fe1c-48d1-89ac-5ae0901db5e5}" StaticName="FoundBy" Name="FoundBy" ShowInEditForm="FALSE"/>
 
<Field Type="DateTime" DisplayName="DateItemFound" Required="TRUE" Format="DateTime" FriendlyDisplayFormat="Relative" ID="{7f1ec3a8-ba55-42dd-90ca-47daae6b6cfa}" StaticName="DateItemFound" Name="DateItemFound" ShowInEditForm="FALSE"><Default>[today]</Default></Field>
 
<Field Type="Note" DisplayName="AdministrativeNotes" Required="FALSE" NumLines="6" RichText="TRUE" RichTextMode="FullHtml" ID="{5c5446a7-85d7-4d34-b883-f41b46968751}" StaticName="Notes" Name="Notes" RestrictedMode="TRUE" AppendOnly="TRUE" ShowInNewForm="FALSE"/>

References