JBone
JBone

Reputation: 3203

Simple Custom Web Control

Hello I am designing a custom .net web control that inherits from the aspx dropdownlist. The idea is to have a dropdownlist that will display year values up until the current year. I want to be able to set a "StartYear" property that the control can start from or else use a default date. I am able to create this control but it is always using the defult date. It seems I am unable to use the property setting in the aspx code in the code behind. My front end code is ....

<customControls:YearDropDownList StartYear="2000" ID="ddlYear" runat="server"/>

and the code behind is

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

    namespace customControls {
    [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
    [DefaultProperty("StartYear")]
    public class YearDropDownList : DropDownList
    {
        public YearDropDownList() {
            for (int i = Int32.Parse(StartYear); i <= DateTime.Now.Year; i++)
            {
                this.Items.Add(new ListItem(i.ToString(), i.ToString()));
            }
        }
        public string StartYear {
            get{
                String s = (String)ViewState["StartYear"];
                return ((s == null) ? "2009":s);
            }
            set{
                ViewState["StartYear"] = value;
            }
        }
    }
    }

Upvotes: 2

Views: 1378

Answers (2)

DiskJunky
DiskJunky

Reputation: 4971

you need to regenerate the list when the property is set like so;

[ToolboxData("<{0}:YearDropDownList runat=\"server\" StartYear=\"[StartYear]\"></{0}:YearDropDownList>")]
[DefaultProperty("StartYear")]
public class YearDropDownList : DropDownList
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        RegenerateList();
    }
    public string StartYear
    {
        get
        {
            String s = (String)this.ViewState["StartYear"];
            return s ?? "2009";
        }
        set
        {
            ViewState["StartYear"] = value;
            RegenerateList();
        }
    }
    public void RegenerateList()
    {
        Items.Clear();
        for (int i = Int32.Parse(this.StartYear); i <= DateTime.Now.Year; i++)
        {
            this.Items.Add(new ListItem(i.ToString(), i.ToString()));
        }
    }
}

I have tested and verified the code above and it most definitely works. An interesting thing that I did notice was that I was able to reproduce your issue for a while in that the property setter was not being hit. I resolved this by right-clicking the solution and clicking Clean. After the solution was cleaned, I right-clicked on the solution again but this time selected Rebuild. That seemed to solve the property setter issue.

Upvotes: 1

Ann L.
Ann L.

Reputation: 13965

To my way of thinking, it doesn't make sense to regenerate the list in the constructor. At the time the control is instantiated, ViewState probably won't be populated yet (though I am not sure of this) and therefore you'll always get your default value being used.

Here's what I'd do:

[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
[DefaultProperty("StartYear")]
public class YearDropDownList : DropDownList
{
    public string StartYear
    {
        get
        {
            String s = (String)ViewState["StartYear"];
            return ((s == null) ? "2009" : s);
        }
        set
        {
            ViewState["StartYear"] = value;
            RegenerateList();
        }
    }

    // Defer regenerating the list until as late as possible    
    protected void OnPreRender(EventArgs e)
    {
        RegenerateList();
        base.OnPreRender(e);
    }

    public void RegenerateList()
    {
        // Remove any existing items.
        this.Items.Clear();
        for (int i = Int32.Parse(StartYear); i <= DateTime.Now.Year; i++)
        {
            this.Items.Add(new ListItem(i.ToString(), i.ToString()));
        }
    }
}

Upvotes: 1

Related Questions