Search code examples
asp.netselectedindexchangedasprepeater

ASP.NET DropDown(s) inside a Repeater SelectedIndexChanged sends the first as sender


Given an asp repeater and a dropdown inside it. I am doing a databind on the repeater and having an ItemDataBound event. Ones the event is fired I am binding the dropdown to some data source and assigning SelectedIndexChanged handler with autopostback true.

The handler is called for each dropdown ( where I have 5 in my case ) but for each of them the "sender" is always the first one.

The view :

<asp:Repeater ID="OptionsRepeater" runat="server">
 <ItemTemplate>
  <asp:DropDownList ID="ddlOptions" runat="server"> 
 </ItemTemplate>
</asp:Repeater>

The repeater datasource code is normal:

OptionsRepeater.DataSource = someDataSource;
OptionsRepeater.ItemDataBound += new RepeaterItemEventHandler(this.OptionsRepeaterItemDataBound);
OptionsRepeater.DataBind();

Event handlers :

        protected virtual void OptionsRepeaterItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                // Get the view class for the current repeater record
                var dropDownData = e.Item.DataItem;
 DropDownList dropDownList = (DropDownList)e.Item.FindControl("ddlOptions");
                if (dropDownList != null)
                {
dropDownList.DataSource = dataSource;
                    dropDownList.DataTextField = "Title";
                    dropDownList.DataValueField = "Id";
                    dropDownList.AutoPostBack = true;
  dropDownList.DataBind();
                    dropDownList.SelectedIndexChanged += DropDownListSelectedIndexChanged;
                 }  
            }
         }



protected void DropDownListSelectedIndexChanged(object sender, EventArgs e)
        {
        //((DropDownList)sender).UniqueID is always the id of the first combo changed and never on the real one.
        }

Solution

  • Ok anyway it is working. The reason why it is not working is that after the databind and after the selection changed event handler it get assigned I was touching the data making .selected=true on some of them :)

    so my mistake thanks for the hints.

    still a fully working solution if someone have the same issue :

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI.WebControls;
    
    namespace WebApplication1
    {
        public partial class WebForm1 : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                DoDataBind();
            }
    
            private void DoDataBind()
            {
                List <List <Tuple<string, string>>> someDataSource = new List<List<Tuple<string, string>>>();
                someDataSource.Add(new List<Tuple<string, string>>
                {
                    new Tuple<string, string>("item1", "item1"),
                    new Tuple<string, string>("item2", "item2"),
                    new Tuple<string, string>("item3", "item3")
                });
                someDataSource.Add(new List<Tuple<string, string>>
                {
                    new Tuple<string, string>("item4", "item4"),
                    new Tuple<string, string>("item5", "item5"),
                    new Tuple<string, string>("item6", "item6")
                });
                someDataSource.Add(new List<Tuple<string, string>>
                {
                    new Tuple<string, string>("item7", "item7"),
                    new Tuple<string, string>("item8", "item8"),
                    new Tuple<string, string>("item9", "item9")
                });
                OptionsRepeater.DataSource = someDataSource;
                OptionsRepeater.EnableViewState = false;
                OptionsRepeater.ItemDataBound += this.OptionsRepeaterItemDataBound;
                OptionsRepeater.DataBind();
            }
    
            /// <summary>
            /// Optionses the repeater item data bound.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="System.Web.UI.WebControls.RepeaterItemEventArgs" /> instance containing the event data.</param>
            private void OptionsRepeaterItemDataBound(object sender, RepeaterItemEventArgs e)
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                {
                    // Get the view class for the current repeater record
                    var dataSource = e.Item.DataItem;
    
                    DropDownList dropDownList = (DropDownList)e.Item.FindControl("ddlOptions");
                    if (dropDownList != null)
                    {
                        dropDownList.DataSource = dataSource;
                        dropDownList.DataTextField = "Item1";
                        dropDownList.DataValueField = "Item2";
                        dropDownList.EnableViewState = false;
                        dropDownList.AutoPostBack = true;
                        dropDownList.DataBind();
                        dropDownList.SelectedIndexChanged += DropDownListSelectedIndexChanged;
                    }
                }
            }
    
            /// <summary>
            /// Drops down list selected index changed.
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="System.EventArgs" /> instance containing the event data.</param>
            private void DropDownListSelectedIndexChanged(object sender, EventArgs e)
            {
                result.Text += ((DropDownList)sender).UniqueID + "<br/>";
    
            }
        }
    }
    

    and the view :

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
           <asp:Repeater ID="OptionsRepeater" runat="server">
             <ItemTemplate>
              <asp:DropDownList ID="ddlOptions" runat="server">  </asp:DropDownList>
             </ItemTemplate>
            </asp:Repeater>
    
            <asp:Literal ID="result" runat="server"></asp:Literal>
        </div>
        </form>
    </body>
    </html>
    

    P.S. if the view state is enabled the event is not fired correctly so disable the state on both the repeater and the dropdown.