2010-10-09 8 views
10

Come faccio a fare un listview non controllare automaticamente un elemento quando faccio doppio clic su di esso?Winform ListView - Interrompe il controllo automatico quando si fa doppio clic

Posso provare ad aggancio nell'evento MouseDoubleClick e impostare la proprietà Checked su false, ma sembra un po 'un trucco. Eseguo anche un calcolo ragionevolmente costoso quando un articolo viene effettivamente verificato e non voglio che questo codice venga eseguito con un doppio clic. Con l'hook di evento sopra, gli eventi ItemCheck & ItemChecked vengono sollevati prima che venga gestito il doppio clic.

C'è una soluzione elegante a questo?

risposta

11

Elegante non è in genere la parola che salta alla mente quando si deve hackerare il modo in cui funziona il controllo nativo di Windows, ma questo è quanto richiesto qui. Prendi in considerazione se vuoi davvero che il tuo controllo si comporti in modo diverso rispetto agli elenchi di tutti gli altri programmi.

Aggiungi una nuova classe al tuo progetto e incolla il codice mostrato di seguito. Compilare. Rilasciare il nuovo controllo dalla parte superiore della casella degli strumenti sul modulo.

using System; 
using System.Windows.Forms; 

class MyListView : ListView { 
    protected override void WndProc(ref Message m) { 
     // Filter WM_LBUTTONDBLCLK 
     if (m.Msg != 0x203) base.WndProc(ref m); 
    } 
} 
+1

Hmmm, questo è il modo meno hacky per farlo .... questo funziona, specialmente se si chiama il metodo OnMouseDoubleClick da WndProc quando viene colpito il messaggio. Questo aggira la gestione del controllo, pur mantenendo l'evento doppio clic che è quello che volevo fare. Grazie! – Gareth

+0

Questo tipo ha una sostituzione simile, dove il doppio clic continua anche a funzionare: http://blogs.msdn.com/b/hippietim/archive/2006/03/27/562256.aspx –

11

Se non si desidera disattivare completamente i messaggi di DoubleClick, è sufficiente disattivare il comportamento di controllo automatico. Puoi invece fare quanto segue:

public class NoDoubleClickAutoCheckListview : ListView 
{ 
    private bool checkFromDoubleClick = false; 

    protected override void OnItemCheck(ItemCheckEventArgs ice) 
    { 
     if (this.checkFromDoubleClick) 
     { 
      ice.NewValue = ice.CurrentValue; 
      this.checkFromDoubleClick = false; 
     } 
     else 
      base.OnItemCheck(ice); 
    } 

    protected override void OnMouseDown(MouseEventArgs e) 
    { 
     // Is this a double-click? 
     if ((e.Button == MouseButtons.Left) && (e.Clicks > 1)) { 
      this.checkFromDoubleClick = true; 
     } 
     base.OnMouseDown(e); 
    } 

    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     this.checkFromDoubleClick = false; 
     base.OnKeyDown(e); 
    } 
} 
+0

ottimo, copre esattamente le mie esigenze e funziona bene per me, grazie! –

2

Ho avuto un problema simile, ed è così che l'ho gestito. Fondamentalmente se l'elemento è selezionato mentre la coordinata x del cursore è maggiore della coordinata x della casella di controllo, quindi annullo il controllo (perché significa che il controllo è stato chiamato quando l'utente ha fatto doppio clic sull'elemento).

Il margine di errore con il numero 22 è solo se l'utente fa doppio clic subito dopo la casella di controllo (molto difficile da fare).

NOTA: mio codice si presuppone che l'utente non fare doppio clic sulla casella di controllo (sia l'utente fa doppio clic l'elemento o gli scatti singoli la casella di controllo)

codice Spiacente è in VB :)

Private Sub lvComboLists_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles lvComboLists.ItemCheck 
    Dim i As Integer = CType(sender, ListView).PointToClient(Cursor.Position).X 
    If i > 22 Then 
     e.NewValue = e.CurrentValue 
    End If 
End Sub 
+1

È necessario diferenziare tra le azioni dell'utente e le azioni del programma per l'evento ItemCheck. L'ho fatto aggiungendo una variabile booleana "MyDoing" nel modulo per consentire il passaggio di controllo originato dal programma. –

+1

Ho trovato questa altra soluzione che sembra ancora più semplice (meno disordinata): http://stackoverflow.com/questions/1406887/only-change-a-listviewitems-checked-state-if-the-checkbox-is-clicked –

1

io uso un metodo molto più semplice di appena resettare il valore della casella di controllo per lo stato originale, cambiando al contrario di ciò che attualmente è:

Private Sub lst_Images_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lst_Images.DoubleClick 
     Dim fIndex As Integer = Me.lst_Images.SelectedIndices(0) 
     ' Undo the changing of the checkbox's state by the double click event. 
     lst_Images.Items(fIndex).Checked = Not lst_Images.Items(fIndex).Checked 

     ' Call the viewer form 
     Dim fViewer As New Image_Edit(fIndex) 
     fViewer.ShowDialog() 
     fViewer.Dispose() 
End Sub 
Problemi correlati