Edit and Insert Mode Templates
In addition to the read-only field templates, Dynamic Data has Edit and Insert field templates. Unlike the Read-Only templates, where the field value is simply displayed on the page, the Edit templates allow the user to modify it using a data entry control, such as a TextBox. By convention, Dynamic Data distinguishes Edit and Insert templates by the _Edit and _Insert they have at the end of their file names, respectively. The Insert templates are a special case of Edit templates, used for editing field values of rows that have not been saved to the database. However, most Edit mode field templates can be used in Insert mode as well.
The Edit field templates are significantly more complex than their read-only counterparts. Consider Listing 3.5, which shows the Edit version of the DateTime field template.
Listing 3.5. DateTime_Edit Field Template (Markup)
<%@ Control Language="C#" CodeBehind="DateTime_Edit.ascx.cs" Inherits="WebApplication.DynamicData.FieldTemplates.DateTime_EditField" %> <asp:TextBox ID="textBox" runat="server" Text='<%# FieldValueEditString %>' Columns="20" /> <asp:RequiredFieldValidator runat="server" ID="requiredFieldValidator" ControlToValidate="textBox" Enabled="false" /> <asp:RegularExpressionValidator runat="server" ID="regularExpressionValidator" ControlToValidate="textBox" Enabled="false" /> <asp:DynamicValidator runat="server" ID="dynamicValidator" ControlToValidate="textBox" /> <asp:CustomValidator runat="server" ID="dateValidator" ControlToValidate="textBox" EnableClientScript="false" Enabled="false" OnServerValidate="DateValidator_ServerValidate" />
In addition to the data entry control, the edit field templates typically have one or more validation controls. The DateTime_Edit template includes a RequiredFieldValidator, a RegularExpressionValidator, a DynamicValidator, and a CustomValidator control. Notice that with the exception of the DynamicValidator, these controls are not enabled by default. They are configured dynamically by the Page_Load event handler defined in the code-behind file shown in Listing 3.6.
Each validator control is configured by a call to the SetUpValidator method of the FieldTemplateUserControl base class. This method enables and configures the validator if the column metadata contains an appropriate data annotation attribute. In particular, the RequiredFieldValidator will be enabled when the column is marked with a RequiredAttribute that does not allow empty strings, and the RegularExpressionValidator will be enabled when the column is marked with a RegularExpressionAttribute. In addition to enabling the validator, the SetUpValidator method also assigns its ErrorMessage and ToolTip properties with an error message either explicitly specified in the data annotation attribute or generated based on the column’s display name.
DynamicValidator is a special validation control provided by Dynamic Data. It ensures all validation attributes applied to the column are invoked to verify its value is correct. This andincludes not only the well-known RequiredAttribute, RangeAttribute, and CustomValidationAttribute, but also all other descendants of the ValidationAttribute that may be applied to the column and are not covered by a specific ASP.NET validator control in this field template.
The CustomValidator control in this field template performs the job you would normally expect the DataTypeAttribute to do. Even though DataTypeAttribute inherits from the ValidationAttribute class, it does not actually perform any validation. Its IsValid method always returns true, which is why the DateTime_Edit template uses the CustomValidator control to ensure that the value entered by the user matches the type specified by the DataTypeAttribute. The SetUpCustomValidator method enables the validator if the column was marked with a DataTypeAttribute and the DateValidator_ServerValidate method performs the actual validation.
Listing 3.6. DateTime_Edit Field Template (Code-Behind)
using System; using System.Collections.Specialized; using System.ComponentModel.DataAnnotations; using System.Web; using System.Web.DynamicData; using System.Web.UI; using System.Web.UI.WebControls; namespace WebApplication.DynamicData.FieldTemplates { public partial class DateTime_EditField : FieldTemplateUserControl { private static DataTypeAttribute DefaultDateAttribute = new DataTypeAttribute(DataType.DateTime); public override Control DataControl { get { return this.textBox; } } protected void Page_Load(object sender, EventArgs e) { this.textBox.ToolTip = this.Column.Description; this.SetUpValidator(this.requiredFieldValidator); this.SetUpValidator(this.regularExpressionValidator); this.SetUpValidator(this.dynamicValidator); this.SetUpCustomValidator(this.dateValidator); } protected override void ExtractValues(IOrderedDictionary dictionary) { dictionary[Column.Name] = this.ConvertEditedValue(this.textBox.Text); } protected void DateValidator_ServerValidate(object source, ServerValidateEventArgs args) { DateTime dummyResult; args.IsValid = DateTime.TryParse(args.Value, out dummyResult); } private void SetUpCustomValidator(CustomValidator validator) { if (this.Column.DataTypeAttribute != null) { switch (this.Column.DataTypeAttribute.DataType) { case DataType.Date: case DataType.DateTime: case DataType.Time: this.EnableCustomValidator(validator, this.Column.DataTypeAttribute); break; } } else if (this.Column.ColumnType.Equals(typeof(DateTime))) { this.EnableCustomValidator(validator, DefaultDateAttribute); } } private void EnableCustomValidator(CustomValidator validator, DataTypeAttribute attribute) { validator.Enabled = true; validator.ErrorMessage = HttpUtility.HtmlEncode( attribute.FormatErrorMessage(this.Column.DisplayName)); } } }