Saturday, September 18, 2010

How to handle out or range values with asp.net dropdownlist - Select other option to add free text

Demo:
There are may occasions where we need to handle out of range values with asp.net DropDownList. In simple terms, at the end of the item list, having a item called, "Other" so that when the user selects the other option, there will be a method to specify free text. So this idea is to have a textbox control next to dropdownlist along with a configurable label. TextBox and the label themself are initially hidden. Once you selected the last (other option) it will show the 'please specify' textbox, where you can enter free text. This is a nice situation to build a custom control so that you dont have to write the same code over and over again. In the following example, I didnt want to hard code the textbox leaving control to render it by itself. Instead I have associated a external place holder (using the property OtherPlaceHolderId) with my control so that it will render the other textbox inside the place holder where you have full control to design as you desire. Even you can place the textbox in a popup dialogue. Please note that the control itself has a property called SelectedText where you have either selected text or entered other text. If you need a multile textbox there is a property called IsMultiline, when you set this property to true, you will get a multi line textbox instead of single line.
Markup:
<asp:FreeDropDownList 
    runat="server" 
    ID="fddlAge" 
    OtherLabel="Please Specify" 
    OtherValue="OtherValue" OtherPlaceHolderId="phOther">        
    <asp:ListItem>1-10</asp:ListItem>
    <asp:ListItem>11-20</asp:ListItem>
    <asp:ListItem>21-30</asp:ListItem>
    <asp:ListItem>31-40</asp:ListItem>
    <asp:ListItem>41-50</asp:ListItem>
    <asp:ListItem Value="OtherValue">Please Specify</asp:ListItem>
</asp:FreeDropDownList>
<asp:PlaceHolder runat="server" ID="phOther" />
<hr />
<asp:Button runat="server" ID="btnSave" Text="Save" />
Control:
public class FreeDropDownList : DropDownList
{
    private TextBox txtOther;
    private Panel pnlOther;
    private string script = @"
        function ShowHideOtherPanel(otherPanel, source, otherValue) {
            var panel = document.getElementById(otherPanel);
            if (panel == undefined) return;
            if (source.options[source.selectedIndex].value == otherValue)
                panel.style.display = ""block"";
            else
                panel.style.display = ""none"";
        }
    ";
    public string OtherLabel { getset; }
    public string OtherValue { getset; }
    public string SelectedText { getset; }
    public string OtherPlaceHolderId { getset; }
    public bool IsMultiline { getset; }
    public FreeDropDownList()
    {
        this.OtherValue = "Other";
        this.OtherPlaceHolderId = string.Empty;
        this.IsMultiline = false;
    }
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        this.CreateControlHeirarchy();
    }
    public void CreateControlHeirarchy()
    {
        this.pnlOther = new Panel() { ID = string.Concat(this.ID, "_OtherPanel"), CssClass = "OtherPanel" };
        this.txtOther = new TextBox() { ID = string.Concat(this.ID, "_TextBox"), CssClass = "OtherTextBox" };
        if (this.IsMultiline) this.txtOther.TextMode = TextBoxMode.MultiLine;
        this.pnlOther.Controls.Add(new Label() { Text = this.OtherLabel, CssClass = "OtherLabel" });
        this.pnlOther.Controls.Add(this.txtOther);
        PlaceHolder phOther = this.Page.FindControl(this.OtherPlaceHolderId) as PlaceHolder;
        Control parent = this.Parent;
        while (phOther == null)
        {
            phOther = parent.FindControl(this.OtherPlaceHolderId) as PlaceHolder;
            if (phOther == null) parent = parent.Parent;
            if (parent == nullbreak;
        }
        if (phOther != null) phOther.Controls.Add(pnlOther);
        this.Attributes.Add("onchange"string.Format("javascript:ShowHideOtherPanel('{0}', this, '{1}')", 
                                                                            pnlOther.ClientID, this.OtherValue));
    }
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (this.SelectedValue.Equals(this.OtherValue))
            this.pnlOther.Attributes.Add("style""display:block;");
        else
            this.pnlOther.Attributes.Add("style""display:none;");
    }
    protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        bool value = base.LoadPostData(postDataKey, postCollection);
        if (this.SelectedValue.Equals(this.OtherValue))
            this.SelectedText = this.txtOther.Text;
        else
        {
            ListItem item = this.Items.FindByValue(this.SelectedValue);
            if (item != nullthis.SelectedText = item.Text;
        }
        return value;
    }
    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), this.GetType().Name, this.script, true);
    }
}

No comments:

iPhone Launch Screen Sizes

iPhone Portrait iOS 8 Retina HT 5.5 = 1242 X 2208 Retna HD 4.7 = 750 X 1134 iPhone Landscape iOS 8 Retina HD 5.5  2208 X 1242 iPho...