Second Life of a Hungarian SharePoint Geek

December 25, 2009

Interacting with other fields from a custom field

Filed under: Custom fields, SharePoint — Tags: , — Peter Holpar @ 19:28

In my recent post I wrote about hiding custom fields just to interact with other fields on the form. Today I will show you how you can create the interaction itself between the fields.

It requires some little tricks, but after we solve the exercise you will see that it is not so complicate and in the forthcoming post I will show you some very powerful example to demonstrate you the usability of this technique.

The main point of the interaction is to get the reference to the other field controls. As I did last time, I will first introduce an interesting approach that – sad but true – does not work.

On the forms the fields are rendered within a ListFieldIterator control. Individual fields of type SPField can be addressed through the Fields collection (inherited from FormComponent) of this class that returns an SPFieldCollection. SPField class has a property called FieldRenderingControl that returns BaseFieldControl. Since the actual ListFieldIterator can be accessed through the parent chain of the actual field control, at the first sight it seems to be a good idea to get the reference for another field using the following really long line of code:

BaseFieldControl fieldControl = ((Microsoft.SharePoint.WebControls.ListFieldIterator)this.Parent.Parent.Parent.Parent.Parent).Fields[fieldName].FieldRenderingControl;

Unfortunately that is not so simple. Although we got a valid reference to a field control, if you try to manipulate its properties, or just to read them, it turns out to be an other instance, not the one displayed on the forms. That is because the FieldRenderingControl returns a new instance of a subclass of the BaseFieldControl, that has really no relation to the actual form.

What other ways there are to get the reference field control? We know that it is a control on the page, but we don’t want to iterate through all of the controls just to find the field. Fortunately the BaseFieldControl class implements a specific interface IValidator and thus included in the Validators collection of the Page class. That is really nice, and we will depend on this behavior in a later post when implementing custom runtime validation of fields.

But for now it is enough to get the reference to the field control using a custom method like this:

  1. protected BaseFieldControl GetFieldControlByName(String fieldNameToSearch)
  2. {
  3.     String iteratorId = GetIteratorByFieldControl(this).ClientID;
  4.     foreach (IValidator validator in Page.Validators)
  5.     {
  6.         if (validator is BaseFieldControl)
  7.         {
  8.             BaseFieldControl baseField = (BaseFieldControl)validator;
  9.             String fieldName = baseField.FieldName;
  10.             if ((fieldName == fieldNameToSearch) &&
  11.                 (GetIteratorByFieldControl(baseField).ClientID == iteratorId))
  12.             {
  13.                 return baseField;
  14.             }
  15.         }
  16.     }
  17.     return null;
  18. }
  19.  
  20. private ListFieldIterator GetIteratorByFieldControl(BaseFieldControl fieldControl)
  21. {
  22.     return (Microsoft.SharePoint.WebControls.ListFieldIterator)this.Parent.Parent.Parent.Parent.Parent;
  23. }

In this method we iterate through the validators on the page, and do some checks in the following order:

  1. Is the field derived from the BaseFieldControl class?
  2. Is the field name the same we are looking for?
  3. An extra check just to be sure: is the field rendered in the same ListFieldIterator as the current field control. Without this check it is possible to have multiple forms on the same page having fields with the same name. We really don’t want to interact with fields in other forms. At least, not now…

Let’s see some simple practical example for usage of this method. Of course, in a production environment you should add some extra logic for null values, exception handling and tracing/logging, but I try to keep it simple now. All of the code snippets are for the field control class that is derived from the BaseFieldControl class.

In the first example we set the field control mode to display. That can you use to prevent users to modify the field value, for example based on the user’s permissions or the value of other field.

  1. protected void SetFieldReadOnly(String fieldName)
  2. {
  3.     BaseFieldControl fieldControl = GetFieldControlByName(fieldName);
  4.     fieldControl.ControlMode = SPControlMode.Display;           
  5. }

Sometimes it is required to hide the field value too. The next example hides the field having the specified name using the same technique we used to inject invisible field to the form.

  1. protected void HideField(String fieldName)
  2. {
  3.     BaseFieldControl fieldControl = GetFieldControlByName(fieldName);
  4.     fieldControl.Visible = false;
  5.     fieldControl.Parent.Parent.Visible = false;
  6. }

You can also set values of other fields using the same technique as illustrated in the code snippet below for a text field.

  1. protected void SetFieldValue(String fieldName, String fieldValue)
  2. {
  3.     TextField fieldText = (TextField)GetFieldControlByName(fieldName);
  4.     fieldText.Value = fieldValue;
  5.     fieldText.Text = fieldValue;
  6. }

You might ask why I don’t show you the simplest case: reading field value. That is because it is really not so simple, and I will describe it in details in a forthcoming post.

It might be useful to use these and similar methods in your custom field control and use that as the boilerplate class for more advanced fields.

The next code snippet assumes that you have a custom list with fields Field1, Field2, Field3, Field4 (all of these of type Single line of text), the default Title field and Field5 of type Choice with values Value1, Value2 and Value3. Furthermore, I suggest you to create your custom field as a “hidden” field as described here.

I’ve created an item in the list before adding our new field to the list columns. The following figure shows the values of the fields on the edit form. You can see there is nothing special on that:

image

We call the methods in the edit and new control modes of the field from the OnLoad method of the field control:

  1. if ((ControlMode == SPControlMode.Edit) || (ControlMode == SPControlMode.New))
  2. {
  3.     HideField("Field1");
  4.     SetFieldReadOnly("Field3");
  5.     SetFieldReadOnly("Field5");
  6.     SetFieldValue("Field4", "text");
  7. }

After building, deploying, and adding the new field to the list, you should see the results immediately on the edit form:

image

It seems to be working perfectly, but if you would like to create you will notice that there is a minor issue with the code. Field3 should be empty, but it contains the text Field3 field value. The other read only field, Field5 of type Choice is displayed correctly.

image

See the second part of this post for the solution of the issue.

Next time I try to plan to show you something more exciting using the same technique.

Advertisements

3 Comments »

  1. […] Second Life of a Hungarian SharePoint Geek If your sword is too short, take one step forward « Interacting with other fields from a custom field […]

    Pingback by Interacting with other fields from a custom field, 2nd part « Second Life of a Hungarian SharePoint Geek — December 30, 2009 @ 22:21

  2. […] Interacting with other fields from a custom field […]

    Pingback by Cross field, cross item, cross list or even more complicated validations on SharePoint forms « Second Life of a Hungarian SharePoint Geek — January 4, 2010 @ 03:00

  3. […] Interacting with other fields from a custom field […]

    Pingback by Creating real multi column fields for SharePoint « Second Life of a Hungarian SharePoint Geek — January 9, 2010 @ 01:35


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: