I decided to create an HTML Edit FieldTemplate after the AJAX Control Toolkit HTML Editor was released and a post (Edit.aspx page hanging on text entry) on the ASP.Net Dynamic Data Forum was posted.
For this we will need two FieldTemplates:
- Html.ascx
- Html_Edit.ascx
The first of the two Html.ascx will display the HTML rendered correctly and the second will use the AJAX Control Toolkit HTML Editor.
The Normal FieldTemplate
<%@ Control
Language="C#"
Inherits="DD_HTMLEditor.Html_Field"
Codebehind="Html.ascx.cs" %>
<asp:Literal
runat="server"
ID="Literal1"
Text="<%# FieldValueEditString %>" />
Listing 1 – Html.ascx
using System;
using System.Web.UI;
namespace DD_HTMLEditor
{
public partial class Html_Field : System.Web.DynamicData.FieldTemplateUserControl
{
public override Control DataControl
{
get
{
return Literal1;
}
}
}
}
Listing 2 – Html.ascx.cs
As you can see this is a direct copy of the Text.ascx FieldTemplate the only change is to Literal1 in the ascx file instead of FieldValueString we are using FieldValueEditString.
Figure 1 – Description Field Showing HTML
The Edit FieldTemplate
<%@ Control
Language="C#"
Inherits="DD_HTMLEditor.Html_EditField"
Codebehind="Html_Edit.ascx.cs" %>
<%@ Register
Assembly="AjaxControlToolkit"
Namespace="AjaxControlToolkit.HTMLEditor"
TagPrefix="cc1" %>
<cc1:Editor
ID="Editor1"
Content='<%# FieldValueEditString %>'
runat="server" />
<asp:RequiredFieldValidator
runat="server"
ID="RequiredFieldValidator1"
CssClass="droplist"
ControlToValidate="Editor1"
Display="Dynamic"
Enabled="false" />
<asp:RegularExpressionValidator
runat="server"
ID="RegularExpressionValidator1"
CssClass="droplist"
ControlToValidate="Editor1"
Display="Dynamic"
Enabled="false" />
<asp:DynamicValidator
runat="server"
ID="DynamicValidator1"
CssClass="droplist"
ControlToValidate="Editor1"
Display="Dynamic" />
Listing 3 – Html_Edit.ascx file
using System;
using System.Collections.Specialized;
using System.Web.UI;
namespace DD_HTMLEditor
{
public partial class Html_EditField : System.Web.DynamicData.FieldTemplateUserControl
{
protected void Page_Load(object sender, EventArgs e)
{
SetUpValidator(RequiredFieldValidator1);
RequiredFieldValidator1.Text = "*";
SetUpValidator(RegularExpressionValidator1);
RegularExpressionValidator1.Text = "*";
SetUpValidator(DynamicValidator1);
DynamicValidator1.Text = "*";
}
protected override void ExtractValues(IOrderedDictionary dictionary)
{
dictionary[Column.Name] = ConvertEditedValue(Editor1.Content);
}
public override Control DataControl
{
get
{
return Editor1;
}
}
}
}
Listing 4 – Html_Edit.ascx.cs file
Here again it’s just the Text_Edit FieldTemplate with a few minor changes (shown in BOLD ITALIC). First we added the AJAC Control Toolkit HTML Editor control to replace the TextBox control and added a reference to the FieldTemplate.
Note:
You could also add a reference for the AJAX Control Toolkit to the web.config
<pages>
<controls>
<add tagPrefix="ajaxToolkit"
namespace="AjaxControlToolkit"
assembly="AjaxControlToolkit"/>
</controls>
</pages>
Figure 2 – Description Field in Edit mode
Next Steps
Next we need to add some of the configurability of the HTML Editor via a custom Attribute.
using System;
using System.Linq;
using System.Web.DynamicData;
using AjaxControlToolkit.HTMLEditor;
namespace DD_HTMLEditor
{
/// <summary>
/// Attribute to identify which column to use as a
/// parent column for the child column to depend upon
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class HtmlEditorAttribute : Attribute
{
/// <summary>
/// Default Contructor
/// </summary>
public HtmlEditorAttribute()
{
}
/// <summary>
/// Active editing panel (Design, Html, Preview) on control loaded
/// </summary>
public AjaxControlToolkit.HTMLEditor.ActiveModeType ActiveMode { get; set; }
/// <summary>
/// If true, editing panel is focused and cursor is set
/// inside it ("Design" or "HTML text") on initial load
/// or editing panel change
/// </summary>
public Boolean AutoFocus { get; set; }
/// <summary>
/// A css class override used to define a custom look
/// and feel for the HTMLEditor. See the HTMLEditor
/// Theming section for more details
/// </summary>
public String CssClass { get; set; }
/// <summary>
/// Sets the path of additional CSS file used for
/// HTMLEditor's content rendering in "Design" panel.
/// If not set, the default CSS file is used which is
/// embedded as a WebResource and is a
/// part of the Toolkit assembly
/// </summary>
public String DesignPanelCssPath { get; set; }
/// <summary>
/// Sets the path of CSS file used for HTMLEditor's
/// content rendering in "Design" and "Preview" panels.
/// If not set, the default CSS file is used which is
/// embedded as a WebResource and is a part of the
/// Toolkit assembly
/// </summary>
public String DocumentCssPath { get; set; }
/// <summary>
/// A css class override used to define a custom look for the
/// HTMLEditor's "HTML text" mode panel. See the HTMLEditor
/// Theming section for more details
/// </summary>
public String HtmlPanelCssClass { get; set; }
/// <summary>
/// If true, Tab key navigation is suppressed inside
/// HTMLEditor control
/// </summary>
public Boolean IgnoreTab { get; set; }
/// <summary>
/// If true, HTMLEditor's content is cleaned up on
/// initial load. MS Word specific tags are removed
/// </summary>
public Boolean InitialCleanUp { get; set; }
/// <summary>
/// If true, JavaScript code is suppressed
/// in HTMLEditor's content
/// </summary>
public Boolean NoScript { get; set; }
/// <summary>
/// If true, all Unicode characters in
/// HTML content are replaced with &#code;
/// </summary>
public Boolean NoUnicode { get; set; }
/// <summary>
/// The client-side script that executes after
/// active mode (editing panel) changed
/// </summary>
public String OnClientActiveModeChanged { get; set; }
/// <summary>
/// The client-side script that executes before
/// active mode (editing panel) changed
/// </summary>
public String OnClientBeforeActiveModeChanged { get; set; }
/// <summary>
/// If true, no white spaces inserted on Tab key
/// press in Design mode. Default Tab key navigation
/// is processing in this case
/// </summary>
public Boolean SuppressTabInDesignMode { get; set; }
/// <summary>
/// Sets the height of the body of the HTMLEditor
/// </summary>
public int Height { get; set; }
/// <summary>
/// Sets the width of the body of the HTMLEditor
/// </summary>
public int Width { get; set; }
}
public static partial class HelperExtansionMethods
{
/// <summary>
/// Get the attribute or a default instance of the attribute
/// if the Column attribute do not contain the attribute
/// </summary>
/// <typeparam name="T">
/// Attribute type
/// </typeparam>
/// <param name="table">
/// Column to search for the attribute on.
/// </param>
/// <returns>
/// The found attribute or a default
/// instance of the attribute of type T
/// </returns>
public static T GetAttributeOrDefault<T>(this MetaColumn column) where T : Attribute, new()
{
return column.Attributes.OfType<T>().DefaultIfEmpty(new T()).FirstOrDefault();
}
}
}
Listing 5 – HtmlEditorAttribute
var htmlAttr = Column.GetAttributeOrDefault<HtmlEditorAttribute>();
if (htmlAttr.ActiveMode != ActiveModeType.Design)
Editor1.ActiveMode = htmlAttr.ActiveMode;
if (htmlAttr.AutoFocus)
Editor1.AutoFocus = true;
if (htmlAttr.CssClass != null)
Editor1.CssClass = htmlAttr.CssClass;
if (htmlAttr.DesignPanelCssPath != null)
Editor1.DesignPanelCssPath = htmlAttr.DesignPanelCssPath;
if (htmlAttr.DocumentCssPath != null)
Editor1.DocumentCssPath = htmlAttr.DocumentCssPath;
if (htmlAttr.Height > 0)
Editor1.Height = htmlAttr.Height;
if (htmlAttr.HtmlPanelCssClass != null)
Editor1.HtmlPanelCssClass = htmlAttr.HtmlPanelCssClass;
if (htmlAttr.IgnoreTab)
Editor1.IgnoreTab = true;
if (htmlAttr.InitialCleanUp)
Editor1.InitialCleanUp = true;
if (htmlAttr.NoScript)
Editor1.NoScript = true;
if (htmlAttr.NoUnicode)
Editor1.NoUnicode = true;
if (htmlAttr.OnClientActiveModeChanged != null)
Editor1.OnClientActiveModeChanged = htmlAttr.OnClientActiveModeChanged;
if (htmlAttr.OnClientBeforeActiveModeChanged != null)
Editor1.OnClientBeforeActiveModeChanged = htmlAttr.OnClientBeforeActiveModeChanged;
if (htmlAttr.SuppressTabInDesignMode)
Editor1.SuppressTabInDesignMode = true;
if (htmlAttr.Width > 0)
Editor1.Width = htmlAttr.Width;
Listing 6 – Attribute setting for Html_Edit.ascx
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using AjaxControlToolkit.HTMLEditor;
namespace DD_HTMLEditor.Models
{
[MetadataType(typeof(CategoryMD))]
public partial class Category
{
public partial class CategoryMD
{
public object CategoryID {get;set;}
public object CategoryName {get;set;}
[UIHint("Html")]
[HtmlEditor(
ActiveMode=ActiveModeType.Preview,
Width=200,
Height=100
)]
public object Description {get;set;}
public object Picture {get;set;}
public object Products {get;set;}
}
}
}
Listing 7 – Metadata
Above we have the attribute Listing 5 and the code Listing 6 to set the properties of the Html Editor in the Html_Edit.ascx FieldTemplate’s Page_Load event, and finally Listing 7 sample metadata.
Figure 3 – Attribute from the Metadata applied
Not Rocket Science but a cool Html Editor (Thanks AJAX Toolkit Guys).
download