checklist c# .net winforms event-handling checkedlistbox

c# - checklist - Comportamiento extraño al alternar el estado verificado del elemento CheckedListBox a través de MouseClick al hacer clic en la misma selección



checkedlistbox c# selected items (1)

El control WinForms CheckedListBox tiene 2 comportamientos predeterminados al hacer clic con el mouse:

  1. Para marcar / desmarcar un elemento, debe hacer clic dos veces en un elemento. El primer clic selecciona el elemento y el segundo alterna el estado de verificación.
  2. Además, un clic posterior del mismo elemento cambiará el estado marcado de ese elemento.

Como una característica de conveniencia, necesitaba permitir a los usuarios cambiar la selección en un solo clic. He logrado esto, por lo que ahora el comportamiento predeterminado # 1 anterior se logra con un solo clic. El problema es que el comportamiento # 2 ya no funciona correctamente al hacer clic en el mismo elemento (es decir, actualmente seleccionado). Funciona bien al saltar entre elementos, lo que se desea, pero requiere hasta 4 clics en el mismo elemento.

Mi solución para esto es llamar a la lógica de conmutación dos veces si el usuario selecciona el mismo elemento repetidamente. Así que a mis preguntas:

  1. Esto funciona, pero ¿por qué? ¿Cuál es el verdadero problema subyacente?
  2. ¿Hay una mejor manera de lograr esto para que pueda funcionar como el comportamiento predeterminado # 2 sin tener que llamar al método dos veces y hacer un seguimiento de mi última selección?

Curiosamente, la depuración del código revela que el estado marcado ha cambiado, pero no aparece en el lado de la interfaz de usuario hasta que se llama dos veces. Pensé que podría estar relacionado con subprocesos, pero no es un evento de reentrada que se dispare y que necesite el uso de BeginInvoke .

Aquí está mi código:

using System.Linq; using System.Windows.Forms; namespace ToggleCheckedListBoxSelection { public partial class Form1 : Form { // default value of -1 since first item index is always 0 private int lastIndex = -1; public Form1() { InitializeComponent(); CheckedListBox clb = new CheckedListBox(); clb.Items.AddRange(Enumerable.Range(1, 10).Cast<object>().ToArray()); clb.MouseClick += clb_MouseClick; this.Controls.Add(clb); } private void clb_MouseClick(object sender, MouseEventArgs e) { var clb = (CheckedListBox)sender; Toggle(clb); // call toggle method again if user is trying to toggle the same item they were last on // this solves the issue where calling it once leaves it unchecked // comment these 2 lines out to reproduce issue (use a single click, not a double click) if (lastIndex == clb.SelectedIndex) Toggle(clb); lastIndex = clb.SelectedIndex; } private void Toggle(CheckedListBox clb) { clb.SetItemChecked(clb.SelectedIndex, !clb.GetItemChecked(clb.SelectedIndex)); } } }

Para reproducir mi problema comente las líneas mencionadas en los comentarios de código y siga estos pasos:

  1. Haga clic en el elemento en el índice 2 - los cambios de estado a marcados .
  2. Con el elemento actual seleccionado, haga clic nuevamente - el estado no cambia. Esperado: sin marcar . Haz clic unas cuantas veces y finalmente cambia.

¡Gracias por leer!


Como una característica de conveniencia, necesitaba permitir a los usuarios cambiar la selección en un solo clic.

No estoy seguro de lo que está sucediendo con el código, pero si establece CheckOnClick en true se hará esto:

CheckOnClick indica si la casilla de verificación debe cambiarse cada vez que se selecciona un elemento. El comportamiento predeterminado es cambiar la selección en el primer clic y luego hacer que el usuario vuelva a hacer clic para aplicar la marca de verificación. En algunos casos, sin embargo, es posible que prefiera que el elemento se verifique tan pronto como se haga clic.