Extending DropDownList in ASP.NET Webform

604 Views Asked by At

I'm trying to create my own drop down list to use on a web page and I just can't get it to work the way I need want.

In it's most basic form I can create a class, inherit from System.Web.UI.WebControls.DropDownList, register it on the page, add the markup and it will at least show a control on the page:

My Class:

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace CustomDropdown
    <DefaultProperty("Text"), ToolboxData("<{0}:DropDownListWithAttributes runat=server></{0}:DropDownListWithAttributes>")>
    Public Class DropDownListWithAttributes
        Inherits System.Web.UI.WebControls.DropDownList

    End Class
End Namespace

Page Register:

<%@ Register TagPrefix="myControls" Namespace="CustomDropdown" %>

Markup:

<myControls:DropDownListWithAttributes ID="ddlMyTestCustomDDL" runat="server"></myControls:DropDownListWithAttributes>

enter image description here

But that's it. That's as far as I can get. I cannot access it from code behind at all. It's like it doesn't exist. I need to be able to fill it with items, trigger events, etc... All the things a normal drop down list would be able to do.

The markup seems to think it can have events: enter image description here

But when I add one the designer breaks: enter image description here

So I do not get normal ddl functionality, I'm unable to access the control from code behind, adding any kind of event breaks stuff...I'm at a loss on how to make this work :(

1

There are 1 best solutions below

0
killerbunnyattack On

Well, with Andrew's suggestion and moving it to it's own project, it seems to be working now. Here's what it looks like:

C# Class Library: DropDownWithAttributes with a single .cs file: DropDownListWithAttributes.cs

using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: TagPrefix("DropDownWithAttributes", "myControl")]
namespace DropDownWithAttributes
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    public class DropDownListWithAttributes : DropDownList
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        protected override object SaveViewState()
        {
            // create object array for Item count + 1
            object[] allStates = new object[this.Items.Count + 1];

            // the +1 is to hold the base info
            object baseState = base.SaveViewState();
            allStates[0] = baseState;

            Int32 i = 1;
            // now loop through and save each Style attribute for the List
            foreach (ListItem li in this.Items)
            {
                Int32 j = 0;
                string[][] attributes = new string[li.Attributes.Count][];
                foreach (string attribute in li.Attributes.Keys)
                {
                    attributes[j++] = new string[] { attribute, li.Attributes[attribute] };
                }
                allStates[i++] = attributes;
            }
            return allStates;
        }

        protected override void LoadViewState(object savedState)
        {
            if (savedState != null)
            {
                object[] myState = (object[])savedState;

                // restore base first
                if (myState[0] != null)
                    base.LoadViewState(myState[0]);

                Int32 i = 1;
                foreach (ListItem li in this.Items)
                {
                    // loop through and restore each style attribute
                    foreach (string[] attribute in (string[][])myState[i++])
                    {
                        li.Attributes[attribute[0]] = attribute[1];
                    }
                }
            }
        }
    }
}

I added the project to my solution and added a reference to DropDownWithAttributes from my web project:

enter image description here

Registered on my page:

<%@ Register TagPrefix="myControl" Namespace="DropDownWithAttributes" Assembly="DropDownWithAttributes" %>

Added the control on the page:

<myControl:DropDownListWithAttributes ID="ddlWithAttribute" runat="server" OnSelectedIndexChanged="ddlWithAttribute_SelectedIndexChanged"></myControl:DropDownListWithAttributes>

That's where things broke before....it's looking better now:

 '''<summary>
    '''ddlWithAttribute control.
    '''</summary>
    '''<remarks>
    '''Auto-generated field.
    '''To modify move field declaration from designer file to code-behind file.
    '''</remarks>
    Protected WithEvents ddlWithAttribute As Global.DropDownWithAttributes.DropDownListWithAttributes

enter image description here