tags:

views:

1910

answers:

5

Is there any way to force a listview control to treat all clicks as though they were done through the Control key?

I need to replicate the functionality of using the control key (selecting an item sets and unsets its selection status) in order to allow the user to easily select multiple items at the same time.

Thank you in advance.

A: 

The Ctrl+Click behavior is as implemented by the browser, and has little to do with the actual .NET Control. The result you're trying to achieve can be acquired with a lot of additional JavaScript - the easiest way would probably be to build a JavaScript control from default that works this way, rather than trying to hack up the listview. Would this be desirable? In that case I could look into it and get back to you with a solution.

Nothing to do with the browser, he's using C# and WinForms!
Ray Hayes
Thanks anyway, Javascript can not be used in the winforms environment.
Evan
+2  A: 

It's not the standard behaviour of the ListView control, even when MultiSelect is set to true.

If you wanted to create your own custom control you would need to do the following:

  1. Derive a control from ListView
  2. add a handler to the "Selected" event.
  3. In the "OnSelected", maintain your own list of selected items.
  4. If the newly selected item is not in your list, add it. If it is, remove it.
  5. In code, select all of the items in your list.

Should be simple enough to implement and feel like multi-select without using the control key!

Ray Hayes
I've been working along these lines myself but wanted to check and see if there was something easier before I went ahead with the fix.Thanks for your answer though.
Evan
Make sure you list of selected items stores the "contents" and not the index. Using the index is easier but it means you need to keep the ListBox.ItemsCollection and your list in sync. Hopefully your object or string is unique enough to keep this relationship!
Ray Hayes
A: 

Drill down through ListviewItemCollection and you can set the Selected property for individual items to true. This will, I believe, emulate the "multi-select" feature that you are trying to reproduce. (Also, as the above commenter mentioned, be sure to have the MultiSelect property of the lisetview set to true.)

BKimmel
+1  A: 

You might want to also consider using Checkboxes on the list view. It's an obvious way to communicate the multi-select concept to your average user who may not know about Ctrl+Click.

From the MSDN page:

The CheckBoxes property offers a way to select multiple items in the ListView control without using the CTRL key. Depending on your application, using check boxes to select items rather than the standard multiple selection method may be easier for the user. Even if the MultiSelect property of the ListView control is set to false, you can still display checkboxes and provide multiple selection capabilities to the user. This feature can be useful if you do not want multiple items to be selected yet still want to allow the user to choose multiple items from the list to perform an operation within your application.

Chris Karcher
A: 

Here is the complete solution that I used to solve this problem using WndProc. Basically, it does a hit test when the mouse is clicked.. then if MutliSelect is on, it will automatically toggle the item on/off [.Selected] and not worry about maintaining any other lists or messing with the ListView functionality.

I haven't tested this in all scenarios, ... it worked for me. YMMV.

public class MultiSelectNoCTRLKeyListView : ListView {
  public MultiSelectNoCTRLKeyListView() {

  }

  public const int WM_LBUTTONDOWN = 0x0201;
  protected override void WndProc(ref Message m) {
    switch (m.Msg) {
      case WM_LBUTTONDOWN:
        if (!this.MultiSelect)
          break;

        int x = (m.LParam.ToInt32() & 0xffff);
        int y = (m.LParam.ToInt32() >> 16) & 0xffff;

        var hitTest = this.HitTest(x, y);
        if (hitTest != null && hitTest.Item != null)
          hitTest.Item.Selected = !hitTest.Item.Selected;

        return;
    }

    base.WndProc(ref m);
  }
}

Thanks,

  • Matthew
Matthew M.