我如何制作一个WinForms ListBox的项目处于打开和关闭状态

问题描述 投票:1回答:3

我需要的功能是在多选模式下复选框和列表框之间的交叉。

对于列表框项目A和B

  • A然后B导致从A移到B的单个选择。

  • A然后按住Control键并单击B会同时选择A和B。

((我想要的是):

  • 然后A导致A切换开和关。

我以为这很容易,但我不知道。也许我遗漏了一些明显的东西,或者我在想错误的方式,没有人真正想要列表框打开或关闭项目。

c# winforms listbox
3个回答
1
投票

如果将SelectionMode设置为MultiSimple,则可以通过单击控制键进行多选并打开和关闭切换。

要使移动选择生效,您可以处理SelectedIndexChanged事件,并在未按下控件的情况下添加一些逻辑以取消选择其他项。如果以后有更多时间,我可以尝试为其创建一些基本代码,但这应该从某个地方开始。


1
投票

如果将ListBox.SelectionMode设置为MultiExtended并在选择时按住控件,则已经具有想要的行为。


0
投票

[如果我正确理解了您的问题,则需要ListBoxSelectionMode.One,该CTLR可以使用SelectionMode.MultiSimpleSelectionMode.MultiExtented修饰符来切换选择。在我的答案下方,只需将ToggleSingleSelection设置为true。另外,它还提供了单击事件,在单击已选择的项目时也会触发这些事件。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Common
{
    public class ListBoxEx : ListBox
    {
        public event ItemClickedEventHandler ItemClick;
        public event ItemClickedEventHandler ItemDoubleClick;

        /// <summary>
        /// Toggle selections when list has SelectionMode.One
        /// </summary>
        public bool ToggleSingleSelection { get; set; }

        int _PreSelectedIndex = -1;
        int _PrevClickedItem = -1;

        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
        }

        protected override void WndProc(ref Message m)
        {
            const int WM_LBUTTONDOWN = 0x201;
            switch (m.Msg)
            {
                case WM_LBUTTONDOWN:
                    // NOTE: Unfortunately SelectedIndex is already setted before OnMouseDown,
                    // so we must intercept mouse click even before to compare
                    _PreSelectedIndex = SelectedIndex;
                    break;
            }

            base.WndProc(ref m);
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);

            // Reset clicked event, also for double click
            _PrevClickedItem = -1;
            int selectedIndex = SelectedIndex;
            if (selectedIndex != -1)
            {
                Rectangle selectedItemRectangle = GetItemRectangle(selectedIndex);
                if (selectedItemRectangle.Contains(e.Location))
                {
                    _PrevClickedItem = selectedIndex;

                    // Check when to toggle selection
                    if (SelectionMode == SelectionMode.One && ToggleSingleSelection && ModifierKeys.HasFlag(Keys.Control)
                        && _PreSelectedIndex != -1 && selectedIndex == _PreSelectedIndex)
                    {
                        SelectedIndex = -1;
                    }

                    if (_PrevClickedItem != -1)
                        OnItemClick(new ItemClickedEventArgs() { ItemIndex = _PrevClickedItem });
                }
            }
        }

        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);

            if (_PrevClickedItem != -1)
                OnItemDoubleClick(new ItemClickedEventArgs() { ItemIndex = _PrevClickedItem });
        }

        protected virtual void OnItemDoubleClick(ItemClickedEventArgs args)
        {
            ItemDoubleClick?.Invoke(this, args);
        }

        protected virtual void OnItemClick(ItemClickedEventArgs args)
        {
            ItemClick?.Invoke(this, args);
        }
    }

    public class ItemClickedEventArgs : EventArgs
    {
        public int ItemIndex { get; set; }
    }

    public delegate void ItemClickedEventHandler(Control sender, ItemClickedEventArgs args);
}
© www.soinside.com 2019 - 2024. All rights reserved.