Introduction

Properties is a central concept in EPiServer that is used to store and present data for pages. A property can either be stored for a single page or as a dynamic property that can be inherited for sub pages. In EPiServer 4, EPiServer.Core.PropertyData was the base class that all properties had to inherit from. These classes were responsible for both processing data and presenting a visual interface for the property. In EPiServer CMS, presentation logic has been removed from PropertyData and classes inheriting from PropertyData. They are still responsible for providing a default user interface through the method EPiServer.Core.PropertyData.CreatePropertyControl that returns a control implementing EPiServer.Core.IPropertyControl. This Interface implements properties and methods that make it possible to load and save data for the properties that are being edited.

EPiServer.Web.PropertyControls namespace

The namespace EPiServer.Web.PropertyControls contains all the default controls for the built-in properties. The abstract base class PropertyDataControl does a lot of the underlying work, lessening the burden for developers creating custom controls. There is no need to inherit from any classes in this namespace. The only thing required is for custom controls to inherit from System.Web.UI.Control and implement the EPiServer.Core.IPropertyControl interface. Some of the more important methods and properties include:

Method Description
CreateDefaultControls() Used to create child controls for view mode.
CreateEditControls() Used to create child controls for edit mode.
ApplyEditChanges() Used to save values from your input controls to the property/properties.*
SetValue(object value) Helper method that sets a value for the current property. Usually called from ApplyEditChanges.
AddErrorValidator(string errorMessage) Used to create a validator for the page if you consider the input data to be invalid.
Property Description
CurrentPage The current page for the closest parent that implements IPageSource.
PropertyData The current property for the control.
Properties Returns a PropertyDataCollection with all properties that are being edited.
RenderType The current RenderType.
SupportsOnPageEdit If the control should render normal controls or "on page edit" controls when in "on page edit" mode.

*IPropertyControl defines the method ApplyChanges() but the default implementation for PropertyDataControl will call the control adapters ApplyChanges method if a control adapter that implements IPropertyControl exists.

Changing the default behavior for built in properties

Control adapters

If you want to change the behavior of a property depending on the web browser of the current request you can map a browser to a control adapter. Since a control adapter has to inherit from an adapter base class, for instance System.Web.UI.WebControls.Adapters.WebControlAdapter, EPiServer has a base class called EPiServer.Web.PropertyControls.Adapters.PropertyDataControlAdapter to facilitate implementation of a custom control adapter for a property. PropertyDataControlAdapter implements many of the properties and methods that exist on PropertyDataControl and the default behavior is to redirect the method back to the current PropertyDataControl. This makes it a simple task to implement the specific methods that you want to change the behavior for. Following is a simple example of a control adapter that overrides the default behavior for EPiServer.Web.PropertyControls.PropertyLongStringControl:

CopyC#
public class PropertyLongStringControlAdapter : PropertyDataControlAdapter
{
    private TextBox _inputControl;

    public override void CreateEditControls()
    {
        _inputControl = AddTextBox();
        _inputControl.ID = Name;
        _inputControl.Text = PropertyData.ToString();
        Control.Controls.Add(_inputControl);
    }
    private TextBox AddTextBox()
    {
        TextBox input = new TextBox();
        input.Rows = 20;
        input.Columns = 40;
        input.Text = ToString();
        input.TextMode = TextBoxMode.MultiLine;

        return input;
    }

    #region IPropertyControl Members

    public override void ApplyChanges()
    {
        SetValue(_inputControl.Text);
    }

    #endregion
}
Note that you have to use Control.Controls.Add() when you want to add a child control in a control adapter. Also note that control adapters are applied even for inherited classes. This means that the behavior of any control inheriting from PropertyDataControl is open for modification by applying a control adapter for PropertyDataControl.

Mapping presentation of properties through PropertyControlClassFactory

Itís also possible to override what control should be used by mapping a PropertyClass through PropertyControlClassFactory. The following code shows how to map a property so that the second argument, that is required to inherit from Control and implement IPropertyControl, is used instead of the default control:

CopyC#
EPiServer.Core.PropertyControlClassFactory.Instance.RegisterClass(
            typeof(EPiServer.Core.PropertyNumber),
            typeof(MyNamespace.MyPropertyDataControl));
PropertyMappings are not applied recursivly for child classes. This means that EPiServer.SpecializedProperties.PropertyXhtmlString will still have its default PropertyControl even though you map PropertyLongString.

Editing several properties with one control

Sometimes you might want to have one edit control that is backed up by several properties. In EPiServer CMS, itís possible to save values to several properties from one control.

This example gives an idea how this could be done:

CopyC#
public override void ApplyEditChanges()
{
    Properties[Name] = new PropertyString(_textbox1.Text);
    Properties[Name + "_extra1"] = new PropertyString(_textbox2.Text);
    Properties[Name + "_extra2"] = new PropertyString(_textbox3.Text);
}

Using postbacks on controls

In EPiServer there were complications when trying to make a postback in a control. With the new model in EPiServer CMS this should no longer be a problem.

This example gives an idea how this could be done:

CopyC#
public override void CreateEditControls()
{
    _inputControl = new TextBox();
    _inputControl.Text = ToString();
    Control.Controls.Add(_inputControl);
    Button button = new Button();
    Control.Controls.Add(button);
    button.Click += new EventHandler(button_Click);
}

void button_Click(object sender, EventArgs e)
{
    _inputControl.Text += "Something Clicked";
}