Las listas desplegables dinámicamente agregadas no se activan Evento SelectedIndexChanged

Vi muchas cosas sobre este tema, pero no puedo encontrar una solución. Agrego muchas listas desplegables con un evento pero no están activando SelectedIndexChanged evet. Aquí está el código del creador drplist:

foreach (var row in cmdSelectCats.ExecuteReader()) { var id = row["ProductCategoryID"].ToString(); var dropDownStatus = new DropDownList {ID = "DrpStatus-" + id}; dropDownStatus.Items.Add(new ListItem("Aktif", "1")); dropDownStatus.Items.Add(new ListItem("Pasif", "2")); dropDownStatus.AutoPostBack = true; dropDownStatus.SelectedIndexChanged += Status_SelectedIndexChanged; var tableCell = new TableCell(); tableCell.Controls.Add(dropDownStatus); dropDownStatus.SelectedValue = row["ProductCategoryStatusID"].ToString(); tableRow.Cells.Add(tableCell); TblCatList.Rows.Add(tableRow); } 

Y por supuesto mi Evento:

 public void Status_SelectedIndexChanged(object sender, EventArgs e) { //DO SOMETHING } 

¿Qué me estoy perdiendo?

Este es un problema común y está relacionado con el ciclo de vida de la página:

Eche un vistazo a las siguientes preguntas:

Haga clic en eventos en Array of buttons

La matriz de botones desaparece después de hacer clic en el evento

Crear dinámicamente un ImageButton

Ahora los pasos básicos para recordar al crear controles dynamics son:

  • Se deben crear controles dynamics en el evento PreInit cuando no se está trabajando con una página maestra, si es así, luego se crean los controles en el evento Init
  • Evite establecer propiedades que se puedan cambiar en cada publicación de estos eventos porque cuando se aplica el estado de vista (en un evento de publicación) las propiedades se anularán
  • Se deben crear controles dynamics cada vez que se publique la página , evite esto if(!this.IsPostBack) this.CreatemyDynamicControls();
  • Cuando crea los controles en los eventos PreInit o Init , sus estados se configurarán automáticamente en un evento de publicación, lo que significa que en el evento LoadComplete sus controles contendrán su estado incluso cuando los vuelva a crear en cada publicación e incluso cuando lo hizo no establece explícitamente su estado. Tenga en cuenta que este comportamiento es diferente cuando se trata de controles creados en tiempo de diseño, en ese caso, el evento donde se ha establecido el estado es el evento Load
  • La suscripción al evento debe ocurrir antes de la completa de PageLoadComplete o no se generarán

Considere la siguiente descripción de MSDN

Si los controles se crean dinámicamente en tiempo de ejecución o declarativamente dentro de plantillas de controles enlazados a datos, sus eventos inicialmente no se sincronizan con los de otros controles en la página. Por ejemplo, para un control que se agrega en tiempo de ejecución, los eventos Init y Load pueden ocurrir mucho más tarde en el ciclo de vida de la página que los mismos eventos para los controles creados de manera declarativa. Por lo tanto, desde el momento en que se crean las instancias, los controles y controles agregados dinámicamente en las plantillas aumentan sus eventos uno tras otro hasta que alcanzan el evento durante el cual se agregaron a la colección de controles.

Lo anterior no es tan claro para mí, pero he encontrado lo siguiente. Los siguientes TextBox se crean en el momento del diseño

  protected void Page_PreInit(object sender, EventArgs e) { this.txtDesignTextBox1.Text = "From PreInit"; this.txtDesignTextBox1.Text += DateTime.Now.ToString(); } protected void Page_Init(object sender, EventArgs e) { this.txtDesignTextBox2.Text = "From Init"; this.txtDesignTextBox2.Text += DateTime.Now.ToString(); } protected void Page_Load(object sender, EventArgs e) { this.txtDesignTextBox3.Text = "From Load"; this.txtDesignTextBox3.Text += DateTime.Now.ToString(); } 

A primera vista, puede pensar que en todas las publicaciones todos los cuadros de texto se actualizan con la fecha actual, pero este no es el caso, ya que se crearon en el momento del diseño y siguen estrictamente el ciclo de vida de la página ASP.Net, lo que significa que su estado se anula después de los eventos PreInit e Init , solo el txtDesignTextBox3 se actualiza en cada publicación porque su propiedad Text se actualiza después de que se haya establecido el estado de la vista (en el evento Load ).

Pero con controles dynamics , el comportamiento es diferente, recuerde la descripción de MSDN:

para un control que se agrega en tiempo de ejecución, los eventos Init y Load pueden ocurrir mucho más tarde en el ciclo de vida de la página

Considera lo siguiente:

  protected void Page_PreInit(object sender, EventArgs e) { var textBox = new TextBox { Text = "From PreInit", Width = new Unit("100%") }; textBox.Text += DateTime.Now.ToString(); this.myPlaceHolder.Controls.Add(textBox); } protected void Page_Init(object sender, EventArgs e) { var textBox = new TextBox { Text = "From Init", Width = new Unit("100%") }; textBox.Text += DateTime.Now.ToString(); this.myPlaceHolder.Controls.Add(textBox); } protected void Page_Load(object sender, EventArgs e) { var textBox = new TextBox { Text = "From Load", Width = new Unit("100%") }; textBox.Text += DateTime.Now.ToString(); this.myPlaceHolder.Controls.Add(textBox); } 

En este caso, los controles se comportan ligeramente diferente, en este caso, en cada publicación, los controles nunca se actualizan ni siquiera los controles creados en el evento Load

La razón es que los eventos del ciclo de vida ocurren mucho más tarde en el ciclo de vida de la página, lo que significa que su estado se anula incluso después del evento Load.

Para resolver esto, puede usar el evento LoadComplete , en este caso puede cambiar el estado de los controles dynamics:

  protected void Page_LoadComplete(object sender, EventArgs e) { var textBox = new TextBox { Text = "From LoadComplete", Width = new Unit("100%") }; textBox.Text += DateTime.Now.ToString(); this.myPlaceHolder.Controls.Add(textBox); } 

En este caso, el estado se actualizará en cada publicación.

Sin embargo, tenga en cuenta que debe suscribirse a eventos de controles dynamics antes del evento LoadComplete o no se generarán.

… Sé que odio este tipo de comportamiento, es por eso que amo MVC

Como referencia rápida para los controles creados en tiempo de diseño: Observe cómo se llama al método LoadViewState después de los eventos PreInit e Init pero antes del evento Load . El evento Load se considera estable porque en este caso puede acceder al estado de vista de sus controles. También observe que el método RaisePostBackEvent representa el evento de control que causó la publicación de nuevo, esto puede ser, SelectedIndexChanged , Click , etc. Este evento se maneja después del evento Load

enter image description here

Para obtener una especificación detallada completa, lea la documentación del ciclo de vida de la página de MSDN.

Por lo general, he visto esto causado por un problema de ciclo de vida de la página. Si el control solo se crea cuando se dispara un evento, cuando su índice cambió el evento, el control no existe para vincularlo en la devolución.

Ejemplo:

  1. MyEvent dispara. Desplegable creado Controlador de eventos especificado.
  2. El evento de índice modificado se activó. La página se recarga. Desplegable no encontrado, no puede disparar.

Debe asegurarse de que se cree el menú desplegable antes de que .NET intente manejar el evento.

Estás perdido:
1- Anular SaveViewState
2- Anular LoadViewState

Proporciono un código de muestra para esta pregunta. Lo pruebo Es trabajo.

ASPX:

 

Código detrás:

 public partial class Default : System.Web.UI.Page { private List values = new List(); protected void Page_Load(object sender, EventArgs e) { } protected override object SaveViewState() { object baseState = base.SaveViewState(); object[] allStates = new object[2]; allStates[0] = baseState; allStates[1] = values; return allStates; } protected override void LoadViewState(object savedState) { object[] myState = (object[])savedState; if (myState[0] != null) base.LoadViewState(myState[0]); if (myState[1] != null) { values = (List)myState[1]; MyRender(); } } protected void Button1_Click(object sender, EventArgs e) { for (int i = 0; i < 10; i++) { DropDownList ddl = new DropDownList(); ddl.ID = "ClientID" + i; ddl.Items.Add("Item 1"); ddl.Items.Add("Item 2"); ddl.AutoPostBack = true; values.Add(ddl.SelectedValue); myDiv.Controls.Add(ddl); } } private void MyRender() { for (int i = 0; i < values.Count; i++) { DropDownList ddl = new DropDownList(); ddl.ID = "ClientID" + i; ddl.Items.Add("Item 1"); ddl.Items.Add("Item 2"); ddl.AutoPostBack = true; ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged); myDiv.Controls.Add(ddl); } } void ddl_SelectedIndexChanged(object sender, EventArgs e) { lblDescription.Text = ((DropDownList)sender).ID + ": Selected Index Changed"; } }