Home

Creating custom controls

Creating a custom control class

Vici MVC allows you to create your own custom controls. These controls can then be used at runtime or they can be bound to a form if you create an associated field attribute for the control.

To create a custom control, you have to derive a class from the abstract Control class and override the GenerateHtml(), HandlePostback() and DataSource methods

To illustrate the creation of a custom control, we will create a simple control representing a text box:

public class CustomTextBoxControl : Control
{ 
  private string _value = ""; 
  private int _maxLength = Int32.MaxValue; 
  private int _size = 0;
   
  public CustomTextBoxControl(string name) : base(name) { } 
  
  public string Value 
  { 
    get { return _value; } 
    set { _value = value ?? ""; } 
  } 
  
  public int MaxLength 
  { 
    get { return _maxLength; } 
    set { _maxLength = value; } 
  } 
  
  public int Size 
  { 
    get { return _size; } 
    set { _size = value; } 
  } 

  protected override string GenerateHtml(View view, string className, string classError) 
  {
    string s = "<input type=\"text\" value=\"" + HttpUtility.HtmlEncode(_value) + "\""; 
  
    s = AddIdAttribute(s); 
    s = AddNameAttribute(s); 
    s = AddClassAttribute(s, className, classNameError); 
    s = AddEnabledAttribute(s); 
    s = AddOnChangeAttribute(s); 

    if (Size != 0) 
      s += " size=\"" + Size + "\""; 
 
    if (MaxLength != Int32.MaxValue) 
      s += " maxlength=\"" + MaxLength + "\""; 

    return s + "/>"; 
  }   

  protected override void HandlePostback(ClientDataCollection postData) 
  { 
    if (postData.Has(Name)) 
      _value = postData.Get(Name); 
  } 

  public override object DataSource 
  { 
    get { return null; } 
    set { }  
  } 
}

Three methods are required for a custom control:

GenerateHtml()

GenerateHtml() is called by the framework when the control needs to be rendered. The method should return plain XHTML.

Parameters:

  • View (type: View): a reference to the view in which the control is rendered. The primary use for this parameter is to add required javascript to the view.
  • className (type: string) and classError (type:string): CSS class names that should be used for the control, depending on the "Error" state of the control. To facilitate the rendering of the HTML code for the CSS class name, you can use the AddClassAttribute() method of the Control base class.

The base Control class has some common properties such as "Id", "Name" and "Enabled". HTML attributes for these properties can be added by calling the following methods:

  • AddIdAttribute()
  • AddNameAttribute()
  • AddEnabledAttribute()
  • AddOnChangeAttribute()

In the example above you can see how you should use these methods.

HandlePostback()

Parameters:

  • postData (type: ClientDataCollection): a collection of data posted with the form containing the control. More information on retrieving client data can be found in the Client Data section.

Common properties for all controls

The abstract Control class has a few properties that are valid for all controls:

PropertyTypeDescription
IdStringThe XHTML id to render the control with. This should be unique across the rendered page. If not set, the framework will generate a unique id for you.
NameStringThe name of the control, which is required and should only be set by the constructor
ErrorBooleanIf set to true, the control will be renderd with the CSS class defined by the CssClassError property. If false, the CSS class defined by CssClass will be used
CssClassStringThe CSS class name to use when rendering the control (if the Error property is false)
CssClassErrorStringThe CSS class name to use when rendering the control (if the Error property is true)
AutoPostBooleanSetting this to true will render the attribute onchange="this.form.submit()"
OnChangeStringDefines a line of javascript to execute when the control is changed on the client. The javascript will be prepended to the javascript generated by the AutoPost property
EnabledBooleanSetting this to false causes the control to be renderd with the disabled="disabled" attribute

It's important to remember that the framework will not autmatically render the required attributes for custom controls. You should call the methods AddIdAttribute(), AddNameAttribute(), etc. This is necessary because not all of these attributes are valid for all kinds of controls. You may also want to handle these properties yourself (for example, when creating complicated composite controls).

Using custom controls in form objects

To use your custom controls in the Vici MVC form handling framework, you should create a companion FormFieldAttribute class. This attribute tells Vici MVC which control to render when generating a form and how to handle the postback from the client.

Let's look at the implementation of the FormCheckboxAttribute:

public class FormCheckboxAttribute : FormFieldAttribute
{
    public string OnClick;

    protected internal override bool IsRightType()
    {
        return FieldType == typeof(bool);
    }

    protected internal override object GetControlValue(Control control)
    {
        return ((CheckBoxControl)control).Checked;
    }

    protected internal override void SetControlValue(Control control, object value)
    {
        ((CheckBoxControl) control).Checked = (bool) value;
    }

    protected internal override Control CreateControl(string name)
    {
        CheckBoxControl control = new CheckBoxControl(name);

        control.OnClick = OnClick;

        return control;
    }

    protected internal override bool Validate(Control control)
    {
        return true;
    }
}

You should create a class derived from FormFieldAttribute, and override the following methods:

CreateControl()

The CreateControl() method should create a control of the required type. This can be a custom control or one of the [[Projects:Mvc:UserGuide:Controls|built-in controls]. You should set all the required properties on the control, according to properties of the attribute. In the example above, we have defined a named proprty OnClick which can be specified when using the attribute. This property is then passed on to the control.

Note the name parameter. This should be used when creating the control (it's always a required constructor parameter for any control)

GetControlValue()

This method should retrieve the value of a control and return it. Make sure the returned value can be converted to the type of the associated field. The type of the associated field can be retrieved by the FieldType property, which is defined in the base class (FormFieldAttribute)

SetControlValue()

This method sholud set the value of the control. The contents of the associated field is passed as parameter.

IsRightType()

This method is called by the framework as a "sanity check", just to make sure you added the attribute to a field of the right type. If you return false, an exception will be thrown. The field type of the associated field is available in the FieldType property of the base class.

Validate()

Validates the value (passed as a parameter). This method should only check if the value is valid for the field type this attribute is associated with. No business rules should be validated in this method (you can use the form's validation mechanism for that)