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

JOKe picture JOKe · Jun 17, 2013 · Viewed 7.5k times · Source

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.
        }

Answer

JOKe picture JOKe · Jun 17, 2013

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.