Gareth
Gareth

Reputation: 2484

Winforms ListView - Stop automatically checking when double clicking

How do I make a listview not automatically check an item when I double click it?

I can try hooking into the MouseDoubleClick event, and set the Checked property to false, but that feels like a bit of an hack. I also run a reasonably expensive calculation when an item is actually checked, and don't want this code to run on a double click. With the event hooking above, the ItemCheck & ItemChecked events are raised before the double click is handled.

Is there an elegent solution to this?

Upvotes: 18

Views: 11346

Answers (5)

Chronos
Chronos

Reputation: 259

A simple solution suggested as answer for similar question was just ok for my use:

private bool inhibitAutoCheck;

private void listView1_MouseDown(object sender, MouseEventArgs e) {
    inhibitAutoCheck = true;
}

private void listView1_MouseUp(object sender, MouseEventArgs e) {
    inhibitAutoCheck = false;
}

private void listView1_ItemCheck(object sender, ItemCheckEventArgs e) {
    if (inhibitAutoCheck)
        e.NewValue = e.CurrentValue;
}

Upvotes: 2

Randall
Randall

Reputation: 41

I use a much simpler method of just resetting the checkbox's value to the original state by changing it to the opposite of what it currently is:

    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

Upvotes: 1

Joakim
Joakim

Reputation: 11978

If you don't want to turn of the DoubleClick messages completely, but just turn off the autocheck behaviour. You can instead do the following:

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

Upvotes: 13

Imad Akel
Imad Akel

Reputation: 21

I had a similar problem, and this is how I handled it. Basically if the item is checked while the cursor's x coordinate is greater than the checkbox's x coordinate, then I cancel the check (because it means the check was called when the user double clicked the item).

The margin of error with the number 22 is only if the user double clicks right after the check box (very hard to do).

NOTE: My code assumes the user will not double click the checkbox (either the user double clicks the item or single clicks the checkbox)

Sorry code is 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

Upvotes: 2

Hans Passant
Hans Passant

Reputation: 941545

Elegant isn't typically the word that jumps to mind when you have to hack the way the native Windows control works, but that's what required here. Do consider if you really want your control to behave differently from the listviews in any other program.

Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form.

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

Upvotes: 13

Related Questions