Listview多选

有没有办法强制listview控件将所有点击视为通过Control键完成?

我需要复制使用控制键的function(选择项目集并取消设置其选择状态),以便用户可以同时轻松选择多个项目。

先感谢您。

即使MultiSelect设置为true,它也不是ListView控件的标准行为。

如果要创建自己的自定义控件,则需要执行以下操作:

  1. 从ListView派生一个控件
  2. 为“Selected”事件添加处理程序。
  3. 在“OnSelected”中,维护您自己的所选项目列表。
  4. 如果新选择的项目不在您的列表中,请添加它。 如果是,请将其删除。
  5. 在代码中,选择列表中的所有项目。

应该很简单,实现和感觉像多选而不使用控制键!

您可能还想考虑在列表视图中使用Checkboxes 。 这是将多选概念传达给可能不了解Ctrl + Click的普通用户的一种明显方式。

从MSDN页面:

CheckBoxes属性提供了一种在不使用CTRL键的情况下在ListView控件中选择多个项目的方法。 根据您的应用程序,使用复选框选择项目而不是标准的多选方法对用户来说可能更容易。 即使ListView控件的MultiSelect属性设置为false,您仍然可以显示复选框并为用户提供多种选择function。 如果您不希望选择多个项目但仍希望允许用户从列表中选择多个项目以在您的应用程序中执行操作,则此function非常有用。

这是我用WndProc解决这个问题的完整解决方案。 基本上,当点击鼠标时它会进行命中测试..然后如果MutliSelect打开,它将自动切换项目开/关[.Selected]而不用担心维护任何其他列表或搞乱ListViewfunction。

我没有在所有场景中对此进行过测试,…它对我有用。 因人而异。

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

这是一个完整的解决方案,它是上面Matthew M.提供的解决方案的修改。

它提供了改进以及一些附加function。

改进: – 左键单击控件可以控制对焦。 – 鼠标右键单击行为一致(单选)

增加的function: – 控件具有一个属性(MultiSelectionLimit),允许您限制一次可以选择的项目数。

在我第一次发布后,我发现了代码的一个小问题。 清除多个选择将导致多次调用ItemSelectionChanged事件。 我找不到用当前inheritance来避免这种情况的方法,所以我采用了一个解决方案,其中bool属性SelectionsBeingCleared将为真,直到取消选择所有选定的项目。 这样,对该属性的简单调用将使得可以避免更新效果,直到清除了所有多个选择。

  public class ListViewMultiSelect : ListView { public const int WM_LBUTTONDOWN = 0x0201; public const int WM_RBUTTONDOWN = 0x0204; private bool _selectionsBeingCleared; ///  /// Returns a boolean indicating if multiple items are being deselected. ///  ///  This value can be used to avoid updating through events before all deselections have been carried out. public bool SelectionsBeingCleared { get { return this._selectionsBeingCleared; } private set { this._selectionsBeingCleared = value; } } private int _multiSelectionLimit; ///  /// The limit to how many items that can be selected simultaneously. Set value to zero for unlimited selections. ///  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 itemsToDeselect = this.SelectedItems.Cast().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().Skip(1)) { item.Selected = false; } this._selectionsBeingCleared = false; this.SelectedItems.Clear(); } } 

向下钻取ListviewItemCollection,您可以将各个项的Selected属性设置为true。 我相信,这将模仿您尝试重现的“多选”function。 (另外,正如上面提到的那样,请确保将lisetview的MultiSelect属性设置为true。)

为了防止其他人搜索并找到这篇文章,接受的解决方案不再有效。 (事实上​​我不确定它是不是)。 为了做你想要的(选择不带修饰键的多个),只需将列表视图选择类型设置为多个,而不是扩展。 单击时多个选择一个项目,并且扩展需要首先按下修改键。

Ctrl + Click行为由浏览器实现,与实际的.NET Control几乎没有关系。 您尝试实现的结果可以通过大量额外的JavaScript获得 – 最简单的方法可能是以默认方式构建一个以这种方式工作的JavaScript控件,而不是试图破解listview。 这会是可取的吗? 在那种情况下,我可以调查一下,并通过解决方案回复您。