2013年11月4日 星期一

[ASP.NET] 解決DropDownList內ListItem Value重複的問題

說明:在設計DropDownList的清單項目時,一般是不會有Value相同的情況,如果有重複,DropDownList會傳回Index最前面的那筆ItemList,例:

<asp:DropDownList ID="ddlTest" runat="server" AutoPostBack="True">
        <asp:ListItem Value="0">請選擇</asp:ListItem>
        <asp:ListItem Value="1">台北</asp:ListItem>
        <asp:ListItem Value="1">新北</asp:ListItem>
        <asp:ListItem Value="2">桃園</asp:ListItem>
        <asp:ListItem Value="2">新竹</asp:ListItem>
</asp:DropDownList>

點選新北,此時DropDownList卻顯示台北,而且無法觸發 SelectedIndexChanged 事件。


作法:參考ASP.NET魔法學院的作法,override DropDownList的方法,將VB版本改為C#:
1. 新增一專案,在類別內加入System.Web.UI.WebControls參考

namespace WebControls
{
    public class CDropDownList: DropDownList
    {
        //將DropDownList的selectedIndex也PostBack回Server端
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            bool blAutoPostBack = false;
            string strScript = string.Empty;

            blAutoPostBack = this.AutoPostBack;
            this.AutoPostBack = false;
            base.AddAttributesToRender(writer);

            if (blAutoPostBack)
            {
                base.Attributes.Remove("onchange");
                strScript = String.Format("__doPostBack('{0}',{1})", this.ClientID, "this.selectedIndex");
                writer.AddAttribute(HtmlTextWriterAttribute.Onchange, strScript);
                this.AutoPostBack = true;
            }
        }

 //判斷PostBack的selectedIndex與原selectedIndex是否相同,不同則觸發SelectedIndexChanged 事件
        protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            string[] strValues = new string[35]; //可自己定義陣列大小
            int iSelectedIndex = 0;

            this.EnsureDataBound();
            strValues = postCollection.GetValues(postDataKey);

            if (strValues != null && Page.Request.Form["__EVENTARGUMENT"].ToString() != "")
            {
                iSelectedIndex = Convert.ToInt32(this.Page.Request.Form["__EVENTARGUMENT"]);
            }

            if (this.SelectedIndex != iSelectedIndex)
            {
                base.SetPostDataSelection(iSelectedIndex);
                return true;
            }
            return false;
        }
    }
}

2. 在web專案加入此專案建置後的dll,在工具箱->選擇項目->加入該元件即可,可自訂前置詞(TagPrefix),定義控制項所在命名空間的別名,預設為cc1。


參考資料:

沒有留言:

張貼留言