Multiple Listview Selection

Is there a way to get the listview control to handle all clicks as if they were made using the control key?

I need to replicate functionality using a control key (select sets of items and deselect its selection status) to allow the user to easily select multiple items at once.

Thanks in advance.

+5
source share
7 answers

This is not the standard behavior of a ListView control, even if the MultiSelect parameter is set to true.

If you want to create your own control, you will need to do the following:

  • Remove a control from a ListView
  • "Selected".
  • "OnSelected" .
  • , . , .
  • .

, - !

+4

, Checkboxes . multi-select , Ctrl + Click.

MSDN:

CheckBoxes ListView CTRL. , . MultiSelect ListView false, . , , , .

+2

, WndProc. , . , MutliSelect , ./. [.Selected] - ListView.

... . 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);
  }
}
+2

, , . .

, .

:

  • .
  • ( )

:

  • (MultiSelectionLimit), , .

. ItemSelectionChanged , ItemSelectionChanged ItemSelectionChanged .
, , bool SelectionsBeingCleared true, .

, , .

public class ListViewMultiSelect : ListView
{
    public const int WM_LBUTTONDOWN = 0x0201;
    public const int WM_RBUTTONDOWN = 0x0204;

    private bool _selectionsBeingCleared;
    /// <summary>
    /// Returns a boolean indicating if multiple items are being deselected.
    /// </summary>
    /// <remarks> This value can be used to avoid updating through events before all deselections have been carried out.</remarks>
    public bool SelectionsBeingCleared
    {
        get
        {
            return this._selectionsBeingCleared;
        }
        private set
        {
            this._selectionsBeingCleared = value;
        }
    }
    private int _multiSelectionLimit;
    /// <summary>
    /// The limit to how many items that can be selected simultaneously. Set value to zero for unlimited selections.
    /// </summary>
    public int MultiSelectionLimit
    {
        get
        {
            return this._multiSelectionLimit;
        }
        set
        {
            this._multiSelectionLimit = Math.Max(value, 0);
        }
    }

    public ListViewMultiSelect()
    {
        this.ItemSelectionChanged += this.multiSelectionListView_ItemSelectionChanged;
    }

    public ListViewMultiSelect(int selectionsLimit)
        : this()
    {
        this.MultiSelectionLimit = selectionsLimit;
    }

    private void multiSelectionListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
    {
        if (e.IsSelected)
        {
            if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit)
            {
                this._selectionsBeingCleared = true;
                List<ListViewItem> itemsToDeselect = this.SelectedItems.Cast<ListViewItem>().Except(new ListViewItem[] { e.Item }).ToList();

                foreach (ListViewItem item in itemsToDeselect.Skip(1)) { 
                    item.Selected = false; 
                }

                this._selectionsBeingCleared = false;
                itemsToDeselect[0].Selected = false;
            }
        }
    }

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_LBUTTONDOWN:
                if (this.SelectedItems.Count == 0 || !this.MultiSelect) { break; }
                if (this.MultiSelectionLimit > 0 && this.SelectedItems.Count > this.MultiSelectionLimit) { this.ClearSelections(); }

                int x = (m.LParam.ToInt32() & 0xffff);
                int y = (m.LParam.ToInt32() >> 16) & 0xffff;
                ListViewHitTestInfo hitTest = this.HitTest(x, y);

                if (hitTest != null && hitTest.Item != null) { hitTest.Item.Selected = !hitTest.Item.Selected; }
                this.Focus();
                return;
            case WM_RBUTTONDOWN:
                if (this.SelectedItems.Count > 0) { this.ClearSelections(); }
                break;
        }
        base.WndProc(ref m);
    }

    private void ClearSelections()
    {
        this._selectionsBeingCleared = true;
        SelectedListViewItemCollection itemsToDeselect = this.SelectedItems;
        foreach (ListViewItem item in itemsToDeselect.Cast<ListViewItem>().Skip(1)) { 
            item.Selected = false; 
        }
        this._selectionsBeingCleared = false;
        this.SelectedItems.Clear();
    }
}
+2

ListviewItemCollection Selected true. , , "multi-select", . ( , , , MultiSelect lisetview true.)

0

, - , . ( , - ). , ( ), , . , .

0
source

The behavior of Ctrl + Click is implemented by the browser and has little in common with real .NET Control. The result that you are trying to achieve can be obtained with a lot of additional JavaScript - the easiest way is probably to create a default JavaScript control that works this way, instead of trying to hack the list. Would it be desirable? In this case, I could study it and come back to you with a solution.

-2
source

All Articles