如何在 C#(Winform)中仅使用鼠标制作多选列表框?

Posted

技术标签:

【中文标题】如何在 C#(Winform)中仅使用鼠标制作多选列表框?【英文标题】:How to make multiselect listbox only with mouse in C# (Winform)? 【发布时间】:2015-03-26 11:03:09 【问题描述】:

我有 listbox 里面有一些东西,我在找这个:

总是以前的项目保持选中状态,如果我点击一个未选中的项目它也被选中但如果它已经被选中它没有被选中。 我使用了这些代码,但效果不佳! 这是我的代码(这个根本不起作用):

public partial class Options_Form : Form

    public Options_Form()
    
        InitializeComponent();
    

    private void Options_Load(object sender, EventArgs e)
    
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
        listboxitemsState_array = new bool[cl.SupportedFiles_stringarray().Length];
    

    private void button2_Click(object sender, EventArgs e)
    
        listBox1.ClearSelected();
        //selecteditemsindex_list.Clear();
    

    //List<int> selecteditemsindex_list = new List<int>();

    bool[] listboxitemsState_array;

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    
        for (int i = 0; i < listboxitemsState_array.Length; i++)
        
            if (listboxitemsState_array[i])
            
                listBox1.SetSelected(i, true);
            
            else
            
                listBox1.SetSelected(i, false);
            
        

        //if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        if (listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)])
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = false;
        
        else
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = true;
        

    

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    

        for (int i = 0; i < listboxitemsState_array.Length; i++)
        
            if (listboxitemsState_array[i])
            
                listBox1.SetSelected(i, true);
            
            else
            
                listBox1.SetSelected(i, false);
            
        

        //if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        if (listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)])
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = false;
        
        else
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            listboxitemsState_array[listBox1.IndexFromPoint(e.X, e.Y)] = true;
        

    


但这个工作但不是很好!

public partial class Options_Form : Form

    public Options_Form()
    
        InitializeComponent();
    

    private void Options_Load(object sender, EventArgs e)
    
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
    

    private void button2_Click(object sender, EventArgs e)
    
        listBox1.ClearSelected();
        selecteditemsindex_list.Clear();
    

    List<int> selecteditemsindex_list = new List<int>();

    private void listBox1_Click(object sender, EventArgs e)
    
        listBox1.ClearSelected();
    

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    
        for (int i = 0; i < selecteditemsindex_list.Count; i++)
        
            listBox1.SetSelected(selecteditemsindex_list[i], true);
        
    

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    

        for (int i = 0; i < selecteditemsindex_list.Count; i++)
        
            listBox1.SetSelected(selecteditemsindex_list[i], true);
        
        if (listBox1.GetSelected(listBox1.IndexFromPoint(e.X, e.Y)))
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), false);
        
        else
        
            listBox1.SetSelected(listBox1.IndexFromPoint(e.X, e.Y), true);
            selecteditemsindex_list.Add(listBox1.IndexFromPoint(e.X, e.Y));
        
    


我该如何解决这个问题!?

【问题讨论】:

【参考方案1】:

我想提一下,您使用SelectionMode.MultiExtended 实现了此功能,但您需要按CTRL + ClickSHIFT + Click

要做到这一点只能用鼠标

1) 当我与@ACE(他提出使用virtualkey 的想法)讨论时,一个更好的解决方案出现在您点击时press CTRL key。在MouseDown 上按CTRL,在MouseUp 上释放CTRL 键。

public partial class Options_Form : Form

    public Options_Form()
    
        InitializeComponent();
    

    private void Options_Load(object sender, EventArgs e)
    
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiSimple;
        listBox1.Size = listBox1.PreferredSize;
    

    [DllImport("user32.dll", SetLastError = true)]
    static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

    public const uint KEYEVENTF_KEYUP = 0x02;
    public const uint VK_CONTROL = 0x11;

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    
        keybd_event(Convert.ToByte(VK_CONTROL), 0, 0, 0);
    

    private void listBox1_MouseUp(object sender, MouseEventArgs e)
    
        keybd_event(Convert.ToByte(VK_CONTROL), 0, Convert.ToByte(KEYEVENTF_KEYUP), 0);
    


2) 我想到的最简单的解决方案(如果你快速按下点击会有一些缺点)是在 MouseClick 事件上使用并有一个 bool 数组该数组中的每个index 都会告诉我是否被选中。

selecteditemsindex_list[selectedIndex] = !selecteditemsindex_list[selectedIndex];

它是如何工作的?

获取 当前索引 并取反 (!) 该索引处的值。这样您就可以使用鼠标获得选择/取消选择功能。

因为我只使用 当前索引 数组中的 其他值 保持未修改,我可以将 SetSelected 用于所有值大批。这样你就可以用鼠标多选了。

public partial class Options_Form : Form

    public Options_Form()
    
        InitializeComponent();
    
    bool[] selecteditemsindex_list;

    private void Options_Load(object sender, EventArgs e)
    
        AceMP_Class cl = new AceMP_Class();
        listBox1.Items.AddRange(cl.SupportedFiles_stringarray());
        listBox1.SelectionMode = SelectionMode.MultiExtended;
        listBox1.Size = listBox1.PreferredSize;
        selecteditemsindex_list = new bool[listBox1.Items.Count];
    

    private void listBox1_MouseDown(object sender, MouseEventArgs e)
    
        var selectedIndex = listBox1.SelectedIndex;
        selecteditemsindex_list[selectedIndex] = !selecteditemsindex_list[selectedIndex];
        for (int i = 0; i < selecteditemsindex_list.Count(); i++)
        
            listBox1.SetSelected(i, selecteditemsindex_list[i]);
        
    

【讨论】:

感谢您的回答 :) 我会尝试并通知您 你知道为什么有人拒绝我的问题吗!? 选择第二个项目时出错 :( 对于这一行:selecteditemsindex_list[selectedIndex] = !selecteditemsindex_list[selectedIndex]; 错误:索引超出了数组的范围。 &是啊其实我想做的就是Ctrl键操作,但是不按住ctrl键直接点击! 是的,它已经初始化了!我认为这会有所帮助:listBox1.SelectedIndex -1 int selectedIndex -1 int 这些是发生错误时的值【参考方案2】:

ListBox 控件有一个属性“SelectionMode” 您可以将其设置为:

    一个 多重简单 多扩展

详情请见link

【讨论】:

以上是关于如何在 C#(Winform)中仅使用鼠标制作多选列表框?的主要内容,如果未能解决你的问题,请参考以下文章

c# Winform PropertyGrid 实现下拉框 多选

C# winform如何设置右击时触发事件

C#在winform上画一张大于全屏的图片(至少3000*3000像素)。在窗口最大化下用鼠标拖动图片,必须画面流畅。

C#在winform上画一张大于全屏的图片(至少3000*3000像素)。在窗口最大化下用鼠标拖动图片,必须画面流畅。

C#在winform上画一张大于全屏的图片(至少3000*3000像素)。在窗口最大化下用鼠标拖动图片,必须画面流畅。

如何在C#的WinForm中制作饼状图和柱状图