2010-11-03 5 views
24

I WinForms CheckedListBox controllo ha 2 comportamenti di default quando si fa clic con il mouse:comportamento strano quando lo stato controllato del commutando CheckedListBox articolo tramite MouseClick quando si fa clic sulla stessa selezione

  1. Al fine di selezionare/deselezionare una voce che sei necessario fare clic su un elemento due volte. Il primo clic seleziona l'elemento e il secondo attiva lo stato di controllo.
  2. Inoltre, un clic successivo dello stesso articolo alterna lo stato selezionato di quell'elemento.

Come funzionalità utile, dovevo consentire agli utenti di alternare la selezione in un clic. Ho raggiunto questo obiettivo, quindi ora il comportamento predefinito # 1 sopra è stato raggiunto con un clic. Il problema è che il comportamento # 2 non funziona più correttamente quando si fa clic sullo stesso oggetto (cioè, attualmente selezionato). Funziona bene quando si salta da un elemento all'altro, cosa che si desidera, ma richiede fino a 4 clic sullo stesso oggetto.

Per risolvere questo problema, chiamare la logica di commutazione due volte se l'utente seleziona ripetutamente lo stesso elemento. Quindi alle mie domande:

  1. Questo funziona, ma perché? Qual è il vero problema di fondo?
  2. Esiste un modo migliore per ottenere questo risultato in modo che possa funzionare come il comportamento predefinito # 2 senza chiamare il metodo due volte e tenere traccia della mia ultima selezione?

Il debugging del codice abbastanza strano rivela che lo stato di controllo è stato modificato ma non viene visualizzato nell'interfaccia utente finché non viene chiamato due volte. Ho pensato che potrebbe essere correlato al threading, ma non è un evento rientranti attivato che potrebbe richiedere l'utilizzo di BeginInvoke.

Ecco il mio codice:

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)); 
     } 
    } 
} 

per riprodurre il mio problema commentare le righe citate nei commenti di codice e attenersi alla seguente procedura:

  1. fare clic sulla voce di indice 2 - cambiamenti di stato a controllato.
  2. Con l'elemento corrente selezionato, fare nuovamente clic su di esso - lo stato non cambia. Previsto: deselezionato. Fare clic su di esso alcune volte e alla fine cambia.

Grazie per la lettura!

risposta

49

Come funzionalità utile, dovevo consentire agli utenti di alternare la selezione in un clic.

non sono sicuro di quello che sta succedendo con il codice, ma l'impostazione CheckOnClick a true farà questo:

CheckOnClick indica se la casella di controllo deve essere attivata ogni volta che si seleziona una voce. Il comportamento predefinito consiste nel modificare la selezione al primo clic e quindi fare in modo che l'utente faccia di nuovo clic per applicare il segno di spunta.In alcuni casi, tuttavia, potresti preferire che l'elemento venga controllato non appena viene fatto clic.

+1

+1: bello e semplice. In qualche modo ho trascurato questa opzione. –

+3

Il mio era impostato su false di default quando il comportamento che volevo era vero. grazie per la risposta, mi ha aiutato anche io! – rizalp1

Problemi correlati