Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have created a custom ListForm template and overide the ListFieldIterator.

I have for example 10 fields in my content type. 5 of these 10 fields must be shown for the creator of the item. The other 5 must be exluded. So I need to check if this is a new item and not an exiting item.

Step 2, we need to check if the item is existing, and the user is going to edit it, I would like to check if the user is member of an custom usergroup. If it is member of this usergroup, I would like to show all the fields and exlude 0 fields. Otherwise, if the user is not a member of the usergroup I would like to show all the 10 fields, but 5 of the 10 fields need to be readonly.

public class CustomListFieldIterator : ListFieldIterator
{
    protected override bool IsFieldExcluded(SPField field)
    {
        if(this is an new item)
        {
            // show only 5 fields
        }
        else
        {
            // this is an existing item, you are editing this item
            // check if the current user is member of an custom usergroup "Auditors"
            SPWeb site = SPContext.Current.Web;
            int groupId = site.Groups["Auditors"].ID;
            if (site.IsCurrentUserMemberOfGroup(groupId))
            {
                // show all the fields
                return false;
            }
            else
            {
                // show all the fields, but 5 of the 10 fields READONLY
            }
        }
    }
}

I defined my custom contenttype as follow with a reference to my custom listForm template:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100839f032740084ac2ae6ea6ab45928a65"
               Name="MyCustomContentType"
               Group="MyCustomContentType"
               Description="MyCustomContentType"
               Inherits="FALSE"
               Version="0">
    <FieldRefs>

      <!-- These are 5 fields always visible-->
      <!-- Everybody is enabled to edit these fields -->
      <FieldRef ID="{EBC17A5D-F320-43D0-A275-7C657EA6F6C9}" Name="RFCDescription"  ShowInEditForm="TRUE" ShowInNewForm="TRUE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{76BF7D5B-6A12-48D1-9827-ADE990B03216}" Name="RFCCompany"  ShowInEditForm="TRUE" ShowInNewForm="TRUE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{9C9ED55A-7025-47F4-9637-27D5D2A1BCAE}" Name="RFCDepartment" ShowInEditForm="TRUE" ShowInNewForm="TRUE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{87DA58EB-3C70-4EF4-B833-1D4A93D60AC9}" Name="RFCClient"  ShowInEditForm="TRUE" ShowInNewForm="TRUE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{56398822-7A4F-4155-A875-ADD09F32D4F2}" Name="RFCContact"  ShowInEditForm="TRUE" ShowInNewForm="TRUE" ShowInDisplayForm="TRUE"/>


      <!-- These are 5 fields only visible in edit mode -->
      <!-- only users in usergroup "Auditors" may change these fields, otherwise readonly -->
      <FieldRef ID="{1A64CE4A-716C-4572-B344-E7CCFE443D50}" Name="RFCScope"  ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{39BC744E-08D4-410C-9D66-B728221634F5}" Name="RFCOperatingCosts"  ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{09B7ED41-C5D0-4B8F-B102-F698164A05B9}" Name="RFCExpertise"  ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="FALSE"/>
      <FieldRef ID="{C95F5617-0C01-49F2-AA5C-8ADE757901F4}" Name="RFCPriority"  ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="TRUE"/>
      <FieldRef ID="{D6E32A83-D6FD-431B-B2CB-625516D3935F}" Name="RFCDatePlanned"  ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="TRUE"/>

<FieldRef ID="{427E04A8-45E5-4243-BFE9-5FDF6FC6205B}" Name="RFCState" ShowInEditForm="TRUE" ShowInNewForm="FALSE" ShowInDisplayForm="TRUE"/>

    </FieldRefs>

    <XmlDocuments>
      <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
        <FormTemplates  xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
          <Display>MyCustomListFormTemplate</Display>
          <Edit>MyCustomListFormTemplate</Edit>
          <New>MyCustomListFormTemplate</New>
        </FormTemplates>
      </XmlDocument>
    </XmlDocuments>

  </ContentType>
</Elements>

I have implemted 5 fields will be visible in new and edit mode. The other 5 fields will be only visible in edit mode.

share|improve this question
    
what version of sharepoint are you using? –  Simon Doy Feb 8 '13 at 16:34
    
Iam using Sharepoint 2010. –  KHA Feb 8 '13 at 17:32
add comment

3 Answers

You have 2 different problems here (plus that it also matters where you use this code).

SPWeb site = SPContext.Current.Web;

To check if a particular user is member of a certain group:

SPGroup managerGroup = site.Groups["ReplaceWithGroupName"];
bool isManager = site.IsCurrentUserMemberOfGroup(managerGroup);

and for the Current user is easier

SPWeb web = // ...
SPGroup group = web.SiteGroups["GroupName"];
if (group.ContainsCurrentUser)
{
  // your code here to hide fields
}

For the 2nd part however SharePoint does not provide the capability to hide FIELDS per Request/User, etc. - you hide them - is for everyone, so updating Fields Visibility is not a solution for you in such situation.

I would go for an easier solution more maintainable solution, that would rely on injecting Javascript in the actual page (via SPD) or a CEWP to control the rendering of fields, by disabling/hiding controls. It is possible to detect in which group the user is part of using details here http://social.technet.microsoft.com/forums/en-ZA/sharepointdevelopmentprevious/thread/dee33fe3-a067-455a-aa65-3bc9bab2e761

share|improve this answer
    
Is something like this not possible?? if(condition) { field.ReadOnlyField = true; field.Update(); } –  KHA Feb 8 '13 at 17:43
    
I've updated my answer - do consider ECMA Javascript as an alternative. When you update a field as in your comment, it shall be the same for everyone. –  C. Marius - MVP Feb 8 '13 at 19:18
    
@user1326231, you can do it without javascript, using custom ListFieldIterator only –  Kai Feb 8 '13 at 19:48
add comment

You can set display in new/edit form property of field to FALSE in the list schema and then add asp controls for these fields to you custom form template. After this you should override

OnSaveContext SPContext.Current.FormContext.OnSaveHandler += OnItemSaved;

In OnItemSaved handler you can collect data from controls and fill item fields.

share|improve this answer
    
You are right, but this does not resolve the issue of hiding/showing selectively fields, unless the New/Edit forms are totally rebuilt - which with C# code is really not sustainable. –  C. Marius - MVP Feb 8 '13 at 19:08
    
@C.Marius, you can use control.visible = group.ContainsCurrentUser in codebehind. –  Alexander Feb 9 '13 at 12:32
add comment

It can be done, but you need to override CreateChildControls in addition to IsFieldExcluded.

Here is a full code for your custom list field iterator:

public class CustomListFieldIterator : ListFieldIterator
{
    protected override void CreateChildControls()
    {
        this.Controls.Clear();
        if (this.ControlTemplate == null)
        {
            throw new ArgumentException("Could not find ListFieldIterator control template.");
        }
        for (int i = 0; i < base.Fields.Count; i++)
        {
            SPField field = base.Fields[i];
            if (!this.IsFieldExcluded(field))
            {
                var child = new CompositeField();
                child.ControlMode = base.ControlMode;
                child.FieldName = field.InternalName;
                var auditors = SPContext.Current.Web.Groups["Auditors"].ID;
                bool isAuditor = SPContext.Current.Web.IsCurrentUserMemberOfGroup(auditors);

                //if field is "Title", we in edit mode and user is not Auditor, make field readonly
                if (field.InternalName.Equals("Title") && ControlMode == SPControlMode.Edit && !isAuditor)
                {
                    child.ControlMode = SPControlMode.Display;
                }
                this.Controls.Add(new LiteralControl("<tr>"));
                this.Controls.Add(child);
                Controls.Add(new LiteralControl("</tr>"));
            }
        }

    }

    protected override bool IsFieldExcluded(SPField field)
    {
        if (base.IsFieldExcluded(field))
        {
            return true;
        }
        //exclude field "Title" in new mode
        if (base.ControlMode == SPControlMode.New)
        {
            if (field.InternalName.Equals("Title"))
            {
                return true;
            }
        }
        return false;
    }
}

Some explanation:
- Field "Title" excluded in a new mode for all users.
- In edit mode field "Title" set as read only for all users, excepts "Auditors" group members.

I have to made a little trick with overriding CreateChildControls to insert on page CompositeField with different ControlMode depending on group membership. CompositeField is actually a control, which render CompositeField rendering template (you can find it in DefaultTemplates.ascx).

So, this can be done without javascript.
Feel free to ask any questions.

share|improve this answer
    
Your solution relies on Application page being built, as building a EDIT/NEW form in such way is not the recomanded way and besides it complicates the deployment or migration –  C. Marius - MVP Feb 8 '13 at 19:10
    
Where did I mention that this is an application page? It's not an application page, it's custom ListFieldIterator class, which is embed as sharepoint rendered template. Look at this article. You can also google another lot of examples of using it in new\edit forms –  Kai Feb 8 '13 at 19:46
    
This works..But..Do I need to add the 5 field title names in the if below: if (field.InternalName.Equals("Title") && field.InternalName.Equals("Field2") && field.InternalName.Equals("Field3") && field.InternalName.Equals("Field4") && field.InternalName.Equals("Field5") && ControlMode == SPControlMode.Edit && !isAuditor) { child.ControlMode = SPControlMode.Display; } –  KHA Feb 8 '13 at 19:49
    
To simplify I recommend you to create List<string> of your excluded fields, and then do following check: if (myExcludedFields.Contains(field.InternalName) && ControlMode == SPControlMode.Edit && !isAuditor) { child.ControlMode = SPControlMode.Display; } –  Kai Feb 8 '13 at 19:55
    
The ListFieldIterator could be very well used in Application pages (exactly as the article also expresses). Your solution is certainly doable, but it requires compiled code, not Sandbox either. –  C. Marius - MVP Feb 8 '13 at 23:50
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.