Friday 12 June 2009

Removed Digsby

Hi I’ve remove the Digsby client after a couple of users complained of browser hijacking (browser opening lots of tabs/pages) when exiting my blog. So unless I can find a safer solution you’ll just have to leave comments of e-mail me.

smile_sad if anyone has a better safer solution just drop me a line and I’ll look into it.

Wednesday 3 June 2009

A Great Buried Sample in Dynamic Data Preview 4 – Dynamic Data Futures

I just thought I’d mention this find ad David Ebbo mentioned overriding MetaTable to get at the table.GetScaffoldColumns() method, and then I found the Dynamic Data Futures sample inside of Preview 4 (which had a billing of being the Futures sample updated to work with Preview 4) and in side the it I found the CustomMetaClasses folder:

The CustomMetaClasses folder

Figure 1 – The CustomMetaClasses folder

This of course give you the sample you need to do this your self my plan is to use this sample to make a MetaTable Class that I can pass in a Lambda function to do all my column generation without ever having to add IAutoFieldGenerator to the page (which in .Net 4.0 will not work on the Details, Edit and Insert pages as they are to be based on FormView to accomodate EntityTemplates).

public class Global : System.Web.HttpApplication
{
    private static MetaModel s_defaultModel = new CustomMetaModel();
    public static MetaModel DefaultModel
    {
        get
        {
            return s_defaultModel;
        }
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        DefaultModel.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration()
        {
            ScaffoldAllTables = true,
            MetadataProviderFactory = (type => new InMemoryMetadataTypeDescriptionProvider(type,
new AssociatedMetadataTypeTypeDescriptionProvider(type))) });

Listing 1 – Adding a DefaultModel based on CustomMetaModel from the CustomMetaClasses folder

Listing 1 shows the addition of the CustomMetaModel to the Global.asax allowing you to override the Meta Classes in one place this is cool.

Thanks again ASP.Net Team HappyWizard

Tuesday 2 June 2009

HTML Editor FieldTemplate for Dynamic Data Using AJAX Control Toolkit Editor

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:

  1. Html.ascx
  2. 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.

Description Field Showing HTML

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>

Description Field in Edit mode

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.

Attribute from the Metadata applied

Figure 3 – Attribute from the Metadata applied

Not Rocket Science but a cool Html Editor (Thanks AJAX Toolkit Guys).

download