Nuestros mejores investigadores han agotado sus provisiones de café, en su búsqueda diariamente por la solución, hasta que Asia encontró el arreglo en Bitbucket así que hoy la comparte contigo.
Solución:
Cuando modifica un elemento en el ListBox (o, en realidad, un elemento en el ObjectCollection asociado del ListBox), el código subyacente realmente elimina y recrea el elemento. Luego selecciona este elemento recién agregado. Por tanto, el índice seleccionado posee ha cambiado y se genera el evento correspondiente.
No tengo una explicación particularmente convincente de por qué el control se comporta de esta manera. Se hizo por conveniencia de programación o simplemente fue un error en la versión original de WinForms, y las versiones posteriores han tenido que mantener el comportamiento por razones de compatibilidad con versiones anteriores. Además, las versiones posteriores han tenido que mantener el mismo comportamiento. incluso si el artículo no fue modificado. Este es el comportamiento contrario a la intuición que estás observando.
Y, lamentablemente, no está documentado, a menos que comprenda por qué está sucediendo y luego sepa que la propiedad SelectedIndex realmente es cambiarse detrás de escena, sin su conocimiento.
Quantic dejó un comentario que apunta a la parte relevante del código en la Fuente de referencia:
internal void SetItemInternal(int index, object value)
Aquí, puede ver que, después de las comprobaciones iniciales de error en tiempo de ejecución, actualiza el ancho máximo del elemento de ListBox, establece el elemento especificado en el interior arrayy luego comprueba si se ha creado el control ListBox nativo. Prácticamente todos los controles de WinForms son envoltorios de los controles nativos de Win32, y ListBox no es una excepción. En su ejemplo, los controles nativos definitivamente se han creado, ya que es visible en el formulario, por lo que el if (owner.IsHandleCreated)
prueba evalúa a true. Luego compara el texto de los elementos para ver si son iguales:
-
Si son diferentes, elimina el elemento original, elimina la selección, agrega un elemento nuevo y lo selecciona si se seleccionó el elemento original. Esto hace que se genere el evento SelectedIndexChanged.
-
Si son iguales y el elemento está seleccionado actualmente, entonces, como indica el comentario, “por razones de compatibilidad”, el evento SelectedIndexChanged se genera manualmente.
Esta SetItemInternal
El método que acabamos de analizar se llama desde el establecedor para la propiedad predeterminada del objeto ListBox.ObjectCollection:
public virtual object this[int index]
get
if (index < 0
set
owner.CheckNoDataSource();
SetItemInternal(index, value);
que es lo que invoca tu código en el exampleButton_Click
controlador de eventos.
No hay forma de evitar que se produzca este comportamiento. Tendrá que encontrar una manera de solucionarlo escribiendo su propio código dentro del método del controlador de eventos SelectedIndexChanged. Podría considerar derivar una clase de control personalizada de la clase ListBox incorporada, anular el método OnSelectedIndexChanged y poner su solución aquí. Esta clase derivada le brindará un lugar conveniente para almacenar información de seguimiento de estado (como variables miembro) y le permitirá usar su control ListBox modificado como un reemplazo directo en todo su proyecto, sin tener que modificar los controladores de eventos SelectedIndexChanged En todas partes.
Pero, honestamente, esto no debería ser un gran problema ni nada que deba solucionar. Su manejo del evento SelectedIndexChanged debería ser trivial, simplemente actualizando algún estado en su formulario, como los controles dependientes. Si no se llevó a cabo ningún cambio visible desde el exterior, los cambios que desencadena serán básicamente no operativos en sí mismos.