Generic Control Builder in ASP.Net

by Mwwhited 29. August 2009 12:08
In response to a question on StackOverFlow I posted a response about possibly using the ControlBuilder class in ASP.Net to get around the lack of generic control support in the ASP.Net designer.  While it may be possible to use the ControlBuilder to dynamically generate controls based on inputs.  Having it work as simply as a generic wrapper seem like it will require a pretty in-depth dive in reflection and the ASP.Net control model.  Because the person asking the question was primarily interested in overriding defaults, my new suggestion would be to either create their own Page or Container class that will recursively search all of the children, check their DefaultValueAttributes on their properties and override with the containers settings if the child is still set to its DefaultValue.
 
 
APS.Net Form Code

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ControlTest._Default" %>
<%@ Register Assembly="GenericServerControls" Namespace="GenericServerControls" TagPrefix="ga" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
    <form id="form1" runat="server">
    <ga:GenericAdapter runat="server" 
            NestedType="System.Web.UI.WebControls.TextBox, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
            ID="genericTest1" ></ga:GenericAdapter>
    </form>
</body>
</html>

Generic Wrapper WebControl

using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace GenericServerControls
{
    [ToolboxData("<{0}:GenericAdapter runat=server></{0}:GENERICADAPTER>")]
    [DefaultProperty("Nested")]
    [ControlBuilder(typeof(GenericAdapterControlBuilder))]
    public class GenericAdapter : WebControl
    {
        public virtual string NestedTypeName { get; set; }

        private Type _nestedType;
        public virtual Type NestedType
        {
            get
            {
                if (_nestedType == null && !string.IsNullOrEmpty(NestedTypeName))
                {
                    var nestedType = Type.GetType(this.NestedTypeName);
                    if (nestedType.IsInstanceOfType(typeof(WebControl)))
                        _nestedType = nestedType;
                }
                return _nestedType;
            }
            protected set { _nestedType = value; }
        }

        protected WebControl _nested;
        public virtual WebControl Nested
        {
            get
            {
                if (_nested == null)
                {
                    var nestedType = this.NestedType;
                    if (nestedType != null)
                    {
                        var constructor = nestedType.GetConstructor(Type.EmptyTypes);
                        var instance = constructor.Invoke(null);
                        var instanceWebControl = instance as WebControl;
                        _nested = instanceWebControl;
                    }
                }
                return _nested;
            }
            set { _nested = value; }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            this.Nested.RenderControl(output);
        }
    }

    [DefaultProperty("Nested")]
    public class GenericAdapter : GenericAdapter where T : WebControl, new()
    {
        public override string NestedTypeName
        {
            get { return this.NestedType.AssemblyQualifiedName; }
            set { }
        }

        public override Type NestedType
        {
            get { return typeof(T); }
            protected set { }
        }
    }

    public class GenericAdapterControlBuilder : ControlBuilder
    {
        public override void Init(
            TemplateParser parser, ControlBuilder parentBuilder,
            Type type, string tagName, string id, IDictionary attribs
            )
        {
            var nestedTypeName = attribs["NestedType"] as string;
            var nestedType = Type.GetType(nestedTypeName);
            var genericAdapter = typeof(GenericAdapter<>).MakeGenericType(nestedType);
            base.Init(parser, parentBuilder, genericAdapter, tagName, id, attribs);
        }
    }
}

Tags: , ,

Programming

Comments are closed

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

RecentPosts

Badges