Working with fields in CSOM

I’ve already detailed how to create a new Taxonomy Field in CSOM – here’s the more generic how to create a general field on a list.:

internal static void CreateFields(ClientContext clientContext, List targetList, string xmlDef)
{
 targetList.Fields.AddFieldAsXml(xmlDef, true, AddFieldOptions.AddFieldInternalNameHint);
 clientContext.ExecuteQuery();
}

And as a bonus, here’s how to set a field to be indexed in the client side object model:

internal static void SetIndex(ClientContext clientContext, List list, string fieldName)
{
	Field f = list.Fields.GetByInternalNameOrTitle(fieldName);
	clientContext.Load(f);
	clientContext.ExecuteQuery();
	f.Indexed = true;
	f.Update();
	list.Update();
	clientContext.ExecuteQuery();
}
Working with fields in CSOM

Hidden fields, and controlling them with the Object Model

SharePoint’s fields can be ‘hidden’ or shown, by setting the SPField.Hidden property. That’s great, but sadly it isn’t that simple. You might want a field hidden, but allow administrators, etc., to ‘unhide’ the field. Then again, sometimes you might want your hidden field to be really hidden, and never ‘unhidden’.

That is actually what SharePoint allows. The SPField.Hidden property also relies on a second property ‘CanToggleHidden’. You can see this in the CAML definition of a field. So you could define a field like:

<Field Type="Text" ID="{449cf8bc-88ce-445a-ac55-11ea0cb71fed}" Hidden="TRUE" CanToggleHidden="TRUE" ... >

Okay, that’s fine – that’d give us a field which is hidden, but we can unhide. Note that by default CanToggleHidden is false, and this led to my problem. Continue reading “Hidden fields, and controlling them with the Object Model”

Hidden fields, and controlling them with the Object Model

Programmatically making a Field Required in SharePoint 2007

One of my colleagues asked an interesting question – programmatically, he’d just added a Site Column to a list, and now he wanted to make that column required on that list. The SPField class had a Required property, and on MSDN this is described as

Gets or sets a Boolean value that determines whether users must enter a value for the field on New and Edit forms.

However, this wasn’t what seemed to happen – although he’d set this to true and update the field, it didn’t make the field required.

He came and asked me why – and I didn’t really know. We knew that the radio button on the column settings did what we wanted …

… so we cracked open reflector to take a look. And this is what we found:

Yup, that’s right – if the field is on a list, the list uses content types, and “Advanced Management of Content Types” isn’t set, then the code gets the first (i.e. Default) content type, and sets the SPFieldLink that relates to that field to be required. Finally, it saves changes to the content type.

So, on a list that doesn’t use content types, to make a field required, you have to update the content type. Interesting…

Programmatically making a Field Required in SharePoint 2007

Hide Column type from Lists

So, you’ve created a new custom Field (or column) type, but you don’t want it to be available to add directly to Lists and Libraries – that is, you want to force users to create columns as Site Columns, and add those to the list. Conversely, maybe you want to prevent a column being created as a Site column, and only available to add directly to lists (though I can’t thinik why).

Well, it turns out that that is possible. In the CAML defining your field in fldtypes_???.xml, you can have something like the following:

<FieldTypes>
    <FieldType>
        <Field Name="TypeName">MyCustomField</Field>
        <Field Name="ParentType">MultiChoice</Field>
        <Field Name="TypeDisplayName">My Custom Field</Field>
        <Field Name="ShowOnColumnTemplateCreate">TRUE</Field>
        <Field Name="ShowOnListCreate">FALSE</Field>
        <Field Name="ShowOnDocumentLibraryCreate">FALSE</Field>
        <Field Name="ShowOnSurveyCreate">FALSE</Field>
        <Field Name="Sortable">FALSE</Field>
        <Field Name="Filterable">TRUE</Field>
        <Field Name="ShowInEditForm">FALSE</Field>
        <Field Name="UserCreatable">TRUE</Field>

ShowOnColumnTemplateCreate controls visibility as a Site Column type. The other ‘Show On X’ values control visibility as a List Column Type for different types of List. You could, therefore, have a Column Type that can only be used on, say, Document Libraries. Hope that helps.

Hide Column type from Lists

Events on Adding/Deleting Fields from Content types

One of the things that’s driven me nuts in SharePoint 2007 is that there are no events to capture when a Field is added to a Content Type. There is an OnAdded event – which sometimes gets used to save Custom Properties of the field (though I prefer Gunnar Peipman’s approach)

Well, no more! In SharePoint 2010, there are now OnAddingToContentType() and OnDeletingFromContentType() methods. We can override this in our custom fields, and this lets us do lots of useful things – like register event handlers, add workflows, or set properties on the content type, which are things that I’ve wanted to do a few times now. So, good news!

Events on Adding/Deleting Fields from Content types

Rendering List Fields from other sites

I had a requirement recently to display the fields of a SharePoint item in another SharePoint site. Now, you can do this with things like the Content Query Web Part, or Data View Web Part, but I was doing a few other things, and specifically, I needed to pull the fields to display from a particular View on the list.

This turned out to be quite an interesting problem. All fields use a subclass of BaseFieldControl, and this is what renders the field – so it appeared to be fairly straight forward. As always, though, there was a little kink to it – you need an SPContext for the site the item comes from, and you need to use this as the contexts for the SPField‘s rendering control:

SPContext ctx = SPContext.GetContext(HttpContext.Current, item.ID, relatedList.ID, relatedWeb);

SPView relatedView = list.DefaultView;

foreach (string vf in relatedView.ViewFields)
{
    SPField fld = relatedList.Fields.GetFieldByInternalName(vf);

    HtmlGenericControl titleLabel = new HtmlGenericControl("H3");
    titleLabel.InnerText = fld.Title;
    this.Controls.Add( titleLabel );

    BaseFieldControl ctl = fld.FieldRenderingControl;
    ctl.ControlMode = SPControlMode.Display;
    ctl.ListId = relatedList.ID;
    ctl.ItemId = item.ID;
    ctl.RenderContext = ctx;
    ctl.ItemContext = ctx;
    ctl.FieldName = fld.Title;
    ctl.ID = Guid.NewGuid().ToString();

    this.Controls.Add( ctl );
}

Groovy!

Rendering List Fields from other sites

"To save to the server, correct the invalid or missing required properties"

I’ve been working on a custom field for, well, a while now, and after making some changes I started to get the error “To save to the server, correct the invalid or missing required properties” when trying to edit a document and save the changes back in Word 2007. This was a little strange, as I’d already sorted out hiding the custom field from the document information panel, and things had been working fine since then.

New documents seemed to be alright, but the older ones weren’t. So, maybe the problems were all the old documents, rather than my field.

Eventually, I came across this knowledgebase article – so I “inspected” the document, removed any of it’s custom data, and resaved it – and it worked fine.

What I think happened here was, I was testing different settings for Content Approval and Versioning on my document libraries. I think the troublesome documents were created when one of those was set to be ‘on’, and I subsequently turned it ‘off’. This meant that the document actually had extra data that referred to a column that no longer existed (I think) – which probably means this is related to Content Approval.

But I’d be curious if anyone else has managed to cause this error, and how they did so.

"To save to the server, correct the invalid or missing required properties"