SPFormContext

Argh, Sezai beat me to this post about SPFormContext and SPControlMode by a few hours! I have to admit my sentiment is the same as his - I'm super stoked to have found this class.

Oftentimes, we need some code to execute, but only in the "published" state (old MCMS terminology). We might want a component to run certain logic, but it's really only relevant if the page is in a live/published state. In other words, the logic does not matter when we are viewing the page as authors, editors, or administrators – we either don't care, or we just don't want the logic to execute. (Could be vice-versa; execute some code only if we're NOT in published state.)

For example, my UE developer asked me to hide all mark-up surrounding a publishing site field. After all, if there isn't any content to display, then why bother rendering the DIV tags, or possibly some heading (H) tags? By performing a check for content, we can avoid a situation where a "News" header appears, but there's nothing it. So, I created a control that wraps around all the mark-up that comprises a UI element/section. If there is no content, the control, and its children, will not render. However, we always want it to render in editing mode; otherwise, we can't add content back in!

This scenario was fairly simple to solve: write a control that inherits from Microsoft.SharePoint.WebControls.BaseFieldControl, and only run the code to check for content if we are in published mode:

if (this.ControlMode == SPControlMode.Display)
{
    // do something.
}

This is all fine and well, since BaseFieldControl can be traced back to Microsoft.SharePoint.WebControls.FormComponent, which is the last point in the hierarchy that has the ControlMode property. If you go further up the tree, Microsoft.SharePoint.WebControls.SPControl does not have the ControlMode property… I have no idea why not.

Why is this a problem? Well, my UE developer wanted to check multiple fields. I could not inherit from BaseFieldControl any longer, since it is meant to represent a single field, not multiple fields. So I decided to inherit from SPControl instead. (In the end, I probably could have inherited from System.Web.UI.WebControls.WebControl, but it seemed to make sense to stick within the SharePoint namespace.)

After much searching, including spending a lot of time in Reflector, specifically searching for Microsoft.SharePoint.Publishing.WebControls.PageDisplayMode and Microsoft.SharePoint.Publishing.WebControls.SPControlMode (both enums), I finally came across this *internal* and *sealed* class in the Microsoft.Office.Server.Utilities namespace: PageUtility. But we can't use it! However, inside PageUtility is a method called IsPageCurrentlyInSomeEditMode() (nice, huh?) and more importantly, a property called FormContextMode, which returns an SPControlMode object… interesting.

Looking closer, I saw a line (similar to) SPContext.Current.FormContext.FormMode (!!). As Sezai pointed out, FormContext is an SPFormContext object, which contains two (potentially) very useful properties: FormMode and FieldControlCollection:

  • FormMode gives us a way to check against the enum SPControlMode to determine what "state" we're in.
  • FieldControlCollection returns an ArrayList of field controls (skipping all the other server controls on the page).

Now, I can do a check like this:

if (SPContext.Current.FormContext.FormMode == SPControlMode.Display)
{
    // do something.
}

Also, with FieldControlCollection, I can iterate over the list of defined fields for the current page, looking for some specified fields. Nice!

SPFormContext is definitely useful, and I'm surprised there hasn't been any postings about it until Sezai came along Wink (try searching for SPFormContext…).

Leave a Reply