views:

1388

answers:

3

Like the subject says I have a listview, and I wanted to add the ctrl + a select all shortcut to it. My first problem is that I can't figure out how to programmatically select all items in a listview. It seems like it should be relatively easy, like ListView.SelectAll() or ListView.Items.SelectAll(), but that doesn't appear to be the case. My next problem is how to define the keyboard shortcut for the listview. Do I do it in a KeyUp event, but then how would you check two presses at once? Or is it a property that you set?

Any help here would be great.

Thanks, Ryan

+4  A: 

You could accomplish both with something like this:

private void listView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A && e.Control)
    {
        listView1.MultiSelect = true;
        foreach (ListViewItem item in listView1.Items)
        {
            item.Selected = true;
        }
    }
}
Shane Fulmer
You have an OR in your if statement - should be an AND.
Andrew Garrison
Fixed - I just saw that. :)
Shane Fulmer
Ha, I knew it was going to be something ridiculously easy. Thanks.
ryanulit
+6  A: 

These works for small lists, but if there are 100,000 items in a virtual list, this could take a long time. This is probably overkill for your purposes, but just in case::

class NativeMethods {
    private const int LVM_FIRST = 0x1000;
    private const int LVM_SETITEMSTATE = LVM_FIRST + 43;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct LVITEM
    {
        public int mask;
        public int iItem;
        public int iSubItem;
        public int state;
        public int stateMask;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string pszText;
        public int cchTextMax;
        public int iImage;
        public IntPtr lParam;
        public int iIndent;
        public int iGroupId;
        public int cColumns;
        public IntPtr puColumns;
    };

    [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessageLVItem(IntPtr hWnd, int msg, int wParam, ref LVITEM lvi);

    /// <summary>
    /// Select all rows on the given listview
    /// </summary>
    /// <param name="list">The listview whose items are to be selected</param>
    public static void SelectAllItems(ListView list) {
        NativeMethods.SetItemState(list, -1, 2, 2);
    }

    /// <summary>
    /// Deselect all rows on the given listview
    /// </summary>
    /// <param name="list">The listview whose items are to be deselected</param>
    public static void DeselectAllItems(ListView list) {
        NativeMethods.SetItemState(list, -1, 2, 0);
    }

    /// <summary>
    /// Set the item state on the given item
    /// </summary>
    /// <param name="list">The listview whose item's state is to be changed</param>
    /// <param name="itemIndex">The index of the item to be changed</param>
    /// <param name="mask">Which bits of the value are to be set?</param>
    /// <param name="value">The value to be set</param>
    public static void SetItemState(ListView list, int itemIndex, int mask, int value) {
        LVITEM lvItem = new LVITEM();
        lvItem.stateMask = mask;
        lvItem.state = value;
        SendMessageLVItem(list.Handle, LVM_SETITEMSTATE, itemIndex, ref lvItem);
    }
}

and you use it like this::

NativeMethods.SelectAllItems(this.myListView);
Grammarian
Are there any prerequisites to getting this code to run? I'm trying it on a regular .NET ListView with CheckBoxes = true. And it's not doing anything.
Esteban Brenes
+1  A: 

First solution won't work if user release Ctrl key first.

You should use KeyDown event instead :

private void listView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A && e.Control)
    {
        listView1.MultiSelect = true;
        foreach (ListViewItem item in listView1.Items)
        {
            item.Selected = true;
        }
    }
}
olorin
I was not able to post a comment on first answer so I posted a new answer (sorry about that)
olorin