Wednesday, June 1, 2011

ASP.NET Dynamic Data - Part 7 - Customize Edit Field Templates


So far we've only concentrated on customize the "simple" fields, the display fields, but what about the edit fields?
Exactly this are the topic of this post. We are going to create a custom field template, and adapt the edit template to our needs.
The field template are created as described in ASP.NET Dynamic Data - Part 3 - Customize Field Templates. This is the template we'll continue working on.

The default template

The default edit template looks like this.
PriceCustom_Edit.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="PriceCustom_Edit.ascx.cs" Inherits="DynamicData_FieldTemplates_PriceCustom_EditField" %>

<asp:TextBox ID="TextBox1" runat="server" Text='<%# FieldValueEditString %>'></asp:TextBox>

<asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1" ControlToValidate="TextBox1" Display="Dynamic" Enabled="false" />
<asp:RegularExpressionValidator runat="server" ID="RegularExpressionValidator1" ControlToValidate="TextBox1" Display="Dynamic" Enabled="false" />
<asp:DynamicValidator runat="server" ID="DynamicValidator1" ControlToValidate="TextBox1" Display="Dynamic" />
PriceCustom_Edit.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Web.DynamicData;

public partial class DynamicData_FieldTemplates_PriceCustom_EditField : System.Web.DynamicData.FieldTemplateUserControl {
    protected void Page_Load(object sender, EventArgs e) {
        TextBox1.MaxLength = Column.MaxLength;
        if (Column.MaxLength < 20)
            TextBox1.Columns = Column.MaxLength;
        TextBox1.ToolTip = Column.Description;

        SetUpValidator(RequiredFieldValidator1);
        SetUpValidator(RegularExpressionValidator1);
        SetUpValidator(DynamicValidator1);
    }
    
    protected override void ExtractValues(IOrderedDictionary dictionary) {
        dictionary[Column.Name] = ConvertEditedValue(TextBox1.Text);
    }

    public override Control DataControl {
        get {
            return TextBox1;
        }
    }
}
By default three validators are present, RequiredFieldValidator, RegularExpressionValidator and DynamicValidator. The RequiredFieldValidator of course makes the field required, the RegularExpressionValidator is empty and does nothing, the DynamicValidator takes care of all the validations defined in the data model.
In this case we'll add a custom validator, that ensures the entered value is an integer between 0 and 100.

Add and implement the custom validator

First we'll add a custom validator in the markup, which looks like this
<asp:CustomValidator runat="server" ID="CustomValidator1" ControlToValidate="TextBox1" Display="Dynamic" OnServerValidate="PriceValidation" />
Next we have to implement the validation method, called PriceValidation. This method checks if this the entered value is a interger between 0 and 100.
protected void PriceValidation(object source, ServerValidateEventArgs args)
{
    bool result = false;
    int value;
    result = Int32.TryParse(TextBox1.Text, out value);
    if (!result)
    {
        CustomValidator1.ErrorMessage = "The entered value is not an integer";
        args.IsValid = false;
        return;
    }

    if (value < 0 || value > 100)
    {
        CustomValidator1.ErrorMessage = "The entered value not between 0 and 100";
        args.IsValid = false;
        return;
    }

    args.IsValid = true;
}
That's it we have now customized the edit field template. This hopefully gives an idea of how to customize the edit template, anything you could normally do in a user control, are possible here.
Here at the end is a screenshot of the custom error message.

1 comment:

  1. When setting up an MVC 3 application, the foreign keys that should allow drop down lists to select an item do not get rendered as drop downs, but as static inputs. This can be resolved by creating a custom display and view for that field.
    We will need to start by creating a custom partial view that will live in “~/Views/Shared/DisplayTemplates/UserGuid.cshtml”, and “~/Views/Shared/EditTemplates/UserGuid.cshtml”. The code for one is located below:
    @model Guid

    @{
    incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
    incMvcSite.Models.SecUser usr = db.SecUsers.Single(u => u.Guid == Model);
    }
    @usr.Display

    This is a display for template that will look up the item in the referenced table and display it. We also need an edit for template as follows:
    @model Guid
    @{
    incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
    SelectList items = new SelectList(db.SecUsers.OrderBy(i => i.Display).ToList(), "Guid", "Display", Model);
    }
    @Html.DropDownList("", items)

    The edit for template is implemented as a drop down list. Originally, we has used static HTML code, but the problem will appear of implementing a “prefix”. Static HTML code does get handled by HTML helpers, so it’s recommended that you use the HTML.DropDownList().
    To force the MVC framework to use the new Display and Edit for templates, we need to annote our model item an add the following line:
    [UIHint("UserGuid")]

    This will cause MVC to use the Display and Edit templates named “UserGuid”, which are just partial views.

    ReplyDelete