C# 在按住Shift键单击时调用多次; ///它第一次触发Shift单击的项目时已选中,下一次触发时 ///激发时,按住Shift键并单击所需的其余项目将被选中。因此,使用 ///存储选择状态的SelectedValueChanged处理程序将在以下情况下失败 ///情景: ///i)用户最多可选择2项 ///ii)用户单击Line1 ///iii)选择的值已更改,但未超过最大值,选择已存储 ///我们称之为Selection_A,它包含第1行 ///iii)用户按下Shift键,并从称为Line3的第一个选项向下移动项目2行 ///iv)SelectedValueChanged激发,该选项显示只有第1行和第3行被激活 ///已选择,因此未超过最大值,选择存储让我们调用它 ///包含第1行、第3行的选项 ///v)SelectedValueChanged会再次触发,此时会选择第1行、第2行和第3行, ///因此,已超过最大值,因此我们将恢复到先前存储的选择 ///这就是选择B,我们想要的是恢复到选择A ///b)MousedDown事件在第一个SelectedValueChanged事件之后触发,因此保存 ///MouseDown中的状态也会在错误的时间存储状态。 私有无效值stbox\u MouseUp(对象发送方,MouseEventArgs e) { if(this.MaxSelection==null) { 返回; } ListBox ListBox=发送方作为ListBox; //存储当前选择 此.previousSelection.Clear(); foreach(列表框中的int-selectedIndex.selectedIndes) { this.previousSelection.Add(selectedIndex); } }

C# 在按住Shift键单击时调用多次; ///它第一次触发Shift单击的项目时已选中,下一次触发时 ///激发时,按住Shift键并单击所需的其余项目将被选中。因此,使用 ///存储选择状态的SelectedValueChanged处理程序将在以下情况下失败 ///情景: ///i)用户最多可选择2项 ///ii)用户单击Line1 ///iii)选择的值已更改,但未超过最大值,选择已存储 ///我们称之为Selection_A,它包含第1行 ///iii)用户按下Shift键,并从称为Line3的第一个选项向下移动项目2行 ///iv)SelectedValueChanged激发,该选项显示只有第1行和第3行被激活 ///已选择,因此未超过最大值,选择存储让我们调用它 ///包含第1行、第3行的选项 ///v)SelectedValueChanged会再次触发,此时会选择第1行、第2行和第3行, ///因此,已超过最大值,因此我们将恢复到先前存储的选择 ///这就是选择B,我们想要的是恢复到选择A ///b)MousedDown事件在第一个SelectedValueChanged事件之后触发,因此保存 ///MouseDown中的状态也会在错误的时间存储状态。 私有无效值stbox\u MouseUp(对象发送方,MouseEventArgs e) { if(this.MaxSelection==null) { 返回; } ListBox ListBox=发送方作为ListBox; //存储当前选择 此.previousSelection.Clear(); foreach(列表框中的int-selectedIndex.selectedIndes) { this.previousSelection.Add(selectedIndex); } },c#,listbox,multi-select,C#,Listbox,Multi Select,我认为这是一种简单的方法,在本例中,限制为6项 string[] lbitems; private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { ListBox listBox = (ListBox)sender; if (listBox.SelectedItems.Count == 7) { for (int i = 0; i < listBox.SelectedI

我认为这是一种简单的方法,在本例中,限制为6项

string[] lbitems;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    ListBox listBox = (ListBox)sender;
    if (listBox.SelectedItems.Count == 7)
    {
        for (int i = 0; i < listBox.SelectedItems.Count; i++)
        {
            bool trovato = false;
            for (int j = 0; j < lbitems.Length; j++)
            {
                if (listBox.SelectedItems[i] == lbitems[j])
                {
                    trovato = true;
                    break;
                }
            }

            if (trovato == false)
            {
                listBox.SelectedItems.Remove(listBox.SelectedItems[i]);
                break;
            }
        }
    }
    else
    {
        lbitems = new string[listBox.SelectedItems.Count];
        listBox.SelectedItems.CopyTo(lbitems, 0);
    }
}
string[]lbitems;
私有无效列表框1\u SelectedIndexChanged(对象发送方,事件参数e)
{
ListBox ListBox=(ListBox)发送方;
如果(listBox.SelectedItems.Count==7)
{
对于(int i=0;i
不幸的是,我发现MousedDown和KeyDown在SelectedValueChanged事件后启动。不过,您已经使用MouseUp设计了一个解决方案,我将在稍后发布。非常感谢。我没有测试它,而是假设他们应该被解雇之前。很抱歉,很高兴听到你找到了解决办法。但是,在“最坏”的情况下,只需创建从ListBox继承的自己的控件,并通过重写WndProc方法将其挂接到windows消息处理中。
    /// <summary>
    /// Handle the ListBox's SelectedValueChanged event, revert the selection if there are too many selected
    /// </summary>
    /// <param name="sender">the sending object</param>
    /// <param name="e">the event args</param>
    void ChildSelectionChanged(object sender, EventArgs e)
    {
        ListBox listBox = sender as ListBox;

        //If the number of selected items is greater than the number the user is allowed to select
        if ((this.MaxSelection != null) && (listBox.SelectedItems.Count > this.MaxSelection))
        {
            //Prevent this method from running while reverting the selection
            listBox.SelectedIndexChanged -= ChildSelectionChanged;

            //Revert the selection to the previously stored selection
            try
            {
                for (int index = 0; index < listBox.Items.Count; index++)
                {
                    if (listBox.SelectedIndices.Contains(index) && !this.previousSelection.Contains(index))
                    {
                        listBox.SetSelected(index, false);
                    }
                }
            }
            catch (ArgumentOutOfRangeException ex)
            {
            }
            catch (InvalidOperationException ex)
            {
            }
            finally
            {
                //Re-enable this method as an event handler for the selection change event
                listBox.SelectedIndexChanged += ChildSelectionChanged;
            }
        }
        else
        {
            RaiseSelectionChangedEvent();
        }
    }

    /// <summary>
    /// Handle the ListBox's MouseUp event, store the selection state.
    /// </summary>
    /// <param name="sender">the sending object</param>
    /// <param name="e">the event args</param>
    /// <remarks>This method saves the state of selection of the list box into a class member.
    /// This is used by the SelectedValueChanged handler such that when the user selects more 
    /// items than they are allowed to, it will revert the selection to the state saved here 
    /// in this MouseUp handler, which is the state of the selection at the end of the previous
    /// mouse click.  
    /// We have to use the MouseUp event since:
    /// a) the SelectedValueChanged event is called multiple times when a Shift-click is made;
    /// the first time it fires the item that was Shift-clicked is selected, the next time it
    /// fires, the rest of the items intended by the Shift-click are selected.  Thus using the
    /// SelectedValueChanged handler to store the selection state would fail in the following
    /// scenario:
    ///   i)   the user is allowed to select 2 items max
    ///   ii)  the user clicks Line1
    ///   iii) the SelectedValueChanged fires, the max has not been exceeded, selection stored
    ///        let's call it Selection_A which contains Line1
    ///   iii) the user Shift-clicks and item 2 lines down from the first selection called Line3
    ///   iv)  the SelectedValueChanged fires, the selection shows that only Line1 and Line3 are
    ///        selected, hence the max has not been exceeded, selection stored let's call it 
    ///        Selection_B which contains Line1, Line3
    ///   v)   the SelectedValueChanged fires again, this time Line1, Line2, and Line3 are selected,
    ///        hence the max has been exceeded so we revert to the previously stored selection
    ///        which is Selection_B, what we wanted was to revert to Selection_A
    /// b) the MouseDown event fires after the first SelectedValueChanged event, hence saving the 
    /// state in MouseDown also stores the state at the wrong time.</remarks>
    private void valuesListBox_MouseUp(object sender, MouseEventArgs e)
    {
        if (this.MaxSelection == null)
        {
            return;
        }

        ListBox listBox = sender as ListBox;

        //Store the current selection
        this.previousSelection.Clear();
        foreach (int selectedIndex in listBox.SelectedIndices)
        {
            this.previousSelection.Add(selectedIndex);
        }
    }
string[] lbitems;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    ListBox listBox = (ListBox)sender;
    if (listBox.SelectedItems.Count == 7)
    {
        for (int i = 0; i < listBox.SelectedItems.Count; i++)
        {
            bool trovato = false;
            for (int j = 0; j < lbitems.Length; j++)
            {
                if (listBox.SelectedItems[i] == lbitems[j])
                {
                    trovato = true;
                    break;
                }
            }

            if (trovato == false)
            {
                listBox.SelectedItems.Remove(listBox.SelectedItems[i]);
                break;
            }
        }
    }
    else
    {
        lbitems = new string[listBox.SelectedItems.Count];
        listBox.SelectedItems.CopyTo(lbitems, 0);
    }
}