tutorial - form c#
¿Ningún evento ItemChecked en un CheckedListBox? (4)
En base a la respuesta de Hans Passant, estoy agregando una versión genérica de VB.NET. Necesitaba un método que se llamaría para todos los controles CheckedListBox en el formulario. Puede modificar esto fácilmente si necesita métodos separados para cada control (sin embargo, agrega algo de redundancia).
Public Class Form1
Delegate Sub ProcessItemCheck(ByRef ListBoxObject As CheckedListBox)
Private Sub ProcessItemCheckSub(ByRef ListBoxObject As CheckedListBox)
'' Do your actual ItemCheck stuff here
End Sub
Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
Dim Objects As Object() = {CheckedListBox1}
BeginInvoke(New ProcessItemCheck(AddressOf ProcessItemCheckSub), Objects)
End Sub
End Class
El control ListView tiene un evento ItemCheck que se dispara antes de que el artículo cambie, y un evento ItemChecked que se dispara después de que el elemento cambia. Vea esta pregunta SO para más detalles.
El control CheckedListBox solo tiene el evento ItemCheck.
¿Cuál es la mejor manera de hacer algo como esto con un CheckedListBox?
private void checkedListBox_ItemChecked(object sender ItemCheckedEventArgs e)
{
okButton.Enabled = (checkedListBox.CheckedItems.Count > 0);
}
Pregunta suplementaria: ¿Por qué no hay ningún evento CheckedListBox.ItemChecked?
Un buen truco para tratar con eventos que no puedes procesar cuando se plantean es retrasar el procesamiento. Lo que puede hacer con el método Control.BeginInvoke (), se ejecuta tan pronto como se envían todos los eventos, se completan los efectos secundarios y el hilo de la interfaz de usuario permanece inactivo nuevamente. A menudo también es útil para TreeView, otro control malhumorado.
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
this.BeginInvoke((MethodInvoker)delegate {
okButton.Enabled = checkedListBox1.CheckedItems.Count > 0;
});
}
Por las dudas: esto no tiene nada que ver con el enhebrado y el truco es bastante barato.
¿Por qué ningún evento ItemChecked? No muy seguro. CheckedListBox simplemente no es un muy buen control. Definitivamente no lo hizo uno de los gurús en el equipo original de Winforms.
Yo uso un temporizador para resolver este problema. Habilite el temporizador mediante el evento ItemCheck. Actúa en el evento Timer''s Tick.
Esto funciona si el elemento se comprueba con un clic del mouse o presionando la barra espaciadora. Aprovecharemos el hecho de que el artículo que acaba de marcarse (o no) siempre es el Elemento seleccionado.
El intervalo del temporizador puede ser tan bajo como 1. Para cuando se produce el evento Tick, se establecerá el nuevo estado verificado.
Este código de VB.NET muestra el concepto. Hay muchas variaciones que puede emplear. Es posible que desee aumentar el intervalo del temporizador para permitir al usuario cambiar el estado de verificación en varios elementos antes de tomar medidas. Luego, en el evento Tick, haga un pase secuencial de todas las
Artículos en la Lista o use su colección CheckedItems para tomar las medidas apropiadas.
Es por eso que primero desactivamos el temporizador en el evento ItemCheck. Desactivar y Activar hace que el período de intervalo vuelva a iniciarse.
Private Sub ckl_ItemCheck(ByVal sender As Object, _
ByVal e As System.Windows.Forms.ItemCheckEventArgs) _
Handles ckl.ItemCheck
tmr.Enabled = False
tmr.Enabled = True
End Sub
Private Sub tmr_Tick(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles tmr.Tick
tmr.Enabled = False
Debug.Write(ckl.SelectedIndex)
Debug.Write(": ")
Debug.WriteLine(ckl.GetItemChecked(ckl.SelectedIndex).ToString)
End Sub
private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) {
int count = this.checkedListBox1.CheckedItems.Count;
if (e.CurrentValue != CheckState.Checked && e.NewValue == CheckState.Checked) {
count += 1;
} else if (e.CurrentValue == CheckState.Checked && e.NewValue != CheckState.Checked) {
count -= 1;
}
this.okButton.Enabled = count > 0;
}