首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Listview多选

Listview多选
EN

Stack Overflow用户
提问于 2008-09-17 14:40:16
回答 7查看 15.4K关注 0票数 6

有没有办法强制listview控件把所有的点击都当作是通过Control键完成的?

我需要复制使用控制键的功能(选择项目设置和取消设置其选择状态),以便允许用户同时轻松地选择多个项目。

提前谢谢你。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2008-09-17 14:57:02

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

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

  1. 从ListView

派生控件

  1. 将处理程序添加到"Selected“事件。
  2. 在"OnSelected“中,维护您自己的选定项目列表。
  3. 如果新选择的项目不在列表中,请添加它。如果是,则将其删除。
  4. 在代码中,选择列表中的所有项目。

应该足够简单,无需使用控制键即可实现并且感觉像多选!

票数 4
EN

Stack Overflow用户

发布于 2013-05-03 10:04:10

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

它提供了一些改进以及一些附加的功能。

改进:

  • 左键单击控件可将焦点置于控件上。
  • 右键单击行为是一致的(单选)

新增功能:

  • 该控件具有一个属性(MultiSelectionLimit),该属性允许您对一次可以选择的项数进行限制。

在我第一次发帖后,我意识到代码有一个小问题。清除多个选择将导致ItemSelectionChanged事件被多次调用。

对于当前继承,我无法避免这种情况,所以我采用了一种解决方案,其中布尔属性SelectionsBeingCleared将为真,直到所有选定的项都被取消选择为止。

这样,在清除所有多个选择之前,对该属性的简单调用就可以避免更新效果。

代码语言:javascript
复制
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();
    }
}
票数 3
EN

Stack Overflow用户

发布于 2008-09-17 15:15:21

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

在MSDN页面中:

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/83945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档