MultiExtended Selection Mode in ListBox when using shift key Bug

MPIon

Well-known member
Joined
Jun 13, 2020
Messages
73
Location
England
Programming Experience
10+
Surely this has to be a bug.
I have a list box which I have set to MultiExtended selection mode, as I want the normal user procedure to be only to select one item, but allow multiple selection if the user holds the Control Key and clicks.
This works, but there is a problem when using the shift key. With the shift key, you can select multiple items in a block, and all are highlighted, but only one is actually selected (the one previously selected).
With MultiSimple, the shift key works correctly and all highlighted items are selected.

I have tried to find a work around for this by switching to MultiSimple and testing for Keys.ControlKey, which if false, would clear the previous selected item. Trouble with this, is the just clicked item is not selected.
I can't find a way to identify the item just clicked in the ListBox, rather than the previously selected item - which is always the first selected item in the list. Hope this is clear.

Can anyone confirm if this is a known bug and a good way to work round it? I've looked and can't find much on this at all.
 
I just tested against .NET Framework 4.8.1 and .NET 6 and it worked correctly in both cases. Please provide a minimal, reproducible example that demonstrates the issue. If we do exactly what you do and do get the same results as you, there's probably something broken on your machine.
 
That multi-select functionality is implemented at the OS level, not at the .NET Framework or .NET Core level. If if there is a bug it is at the Windows User or GDI level. See LBS_EXTENDEDSEL and LBS_MULTISEL.
 
That multi-select functionality is implemented at the OS level, not at the .NET Framework or .NET Core level. If if there is a bug it is at the Windows User or GDI level. See LBS_EXTENDEDSEL and LBS_MULTISEL.

Thanks. I guess no-one has used this then, in a Net 7 project, otherwise they would have noticed the same bug.
I have pretty much got round this now by reverting to MultiSimple and using MouseClick rather than Click and the following code :-
C#:
        private void TagList_MouseClick(object sender, MouseEventArgs e)
        {
            if (ModifierKeys != Keys.Control)
            {
                TagList.ClearSelected();
                TagList.SelectedIndex = TagList.IndexFromPoint(e.Location);
            }
This ensures only one item is selected unless Control is held whilst clicking.

I have to wonder why MultipleExtended is included as an option in the ListBox if it does not work properly.
 
I just tested against .NET Framework 4.8.1 and .NET 6 and it worked correctly in both cases. Please provide a minimal, reproducible example that demonstrates the issue. If we do exactly what you do and do get the same results as you, there's probably something broken on your machine.

I'm using Windows 10 and Net 7 for the project and it is definitely a bug at least on my machine. With MultiExtended, I can see multiple items in the ListBox highlighted in blue when using the shift key, but as far the the code is concerned, only one item is actually selected - as determined by the code :-
C#:
            foreach (string tag in TagList.SelectedItems)

Anyway, I've got a work around for this, so I've got to move on. Thanks for replying.
 
I think that the problem is that you are looking at the list selection at the time of your mouse click event. If that is true, then you are using the wrong event. The intended use of the listbox for it to be used independently -- not micromanaged by watching all the low level mouse events. You are supposed just tell Windows to create a list box in your dialog box and tell it that it can or cannot do multiselect. Later when the OK button on your dialog box is pressed, then you ask the list box what items are selected. Windows programming is not like web programming.
 
I think that the problem is that you are looking at the list selection at the time of your mouse click event. If that is true, then you are using the wrong event. The intended use of the listbox for it to be used independently -- not micromanaged by watching all the low level mouse events. You are supposed just tell Windows to create a list box in your dialog box and tell it that it can or cannot do multiselect. Later when the OK button on your dialog box is pressed, then you ask the list box what items are selected. Windows programming is not like web programming.

Thanks for the reply. I'll have to think about that one.
I'm not using a dialog box though and don't have an OK button. I just have a list box (created at design time) and when an item is clicked, it takes action. I might try a test with a button and see if when it is pressed if does show all highlighted items in the ListBox as selected - in which case this may be another timing issue.

Update
Just tried that and even though there are clearly 12 items highlighted in Blue in my ListBox, when I press the button it is only showing 1 as selected (using code) :-
C#:
        private void button1_Click(object sender, EventArgs e)
        {
            foreach (string tag in TagList.SelectedItems)
            {
                MessageBox.Show(tag.ToString());
            }
        }
 
Last edited:
Yes, that is expected behavior because during the click event, the windows listbox still has not yet had a chance to update its selected items collection while handling the mouse click. As I said, you are likely using the wrong event.

Try using the "validating" or "validated" event and see if the the selected items collection has been updated.
 
Yes, that is expected behavior because during the click event, the windows listbox still has not yet had a chance to update its selected items collection while handling the mouse click. As I said, you are likely using the wrong event.

Try using the "validating" or "validated" event and see if the the selected items collection has been updated.

Not sure about that, because even if I wait for a minute after the click event on the list box before pressing the button, the code is still only showing one item as selected even though multiple are highlighted. Incidentally, my understanding of a listbox, which I have used quite extensively in c# and Access projects, is that you populate the list box with items and then wait for one of the items to be clicked. That then instigates action - e.g. it might be opening up a file shown in the list box. So the appropriate event for that is the Click event in the ListBox.
 
Can you show you minimal code that reproduces the problem?

Here is my minimal code that shows that there is no issue:
C#:
class MyTestForm : Form
{
    MyTestForm()
    {
        var listBox = new ListBox()
        {
            SelectionMode = SelectionMode.MultiExtended,
            Dock = DockStyle.Fill
        };
        for (int i = 0; i < 10; i++)
            listBox.Items.Add($"Item {i}");
        Controls.Add(listBox);

        listBox.SelectedIndexChanged += (o, e) =>
        {
            var items = string.Join(",", listBox.SelectedItems.Cast<string>());
            this.Text = $"{listBox.SelectedItems.Count}: {items}";
        };
    }

    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();
        Application.Run(new MyTestForm() { Size = new Size(800, 600)});
    }
}
 
Can you show you minimal code that reproduces the problem?
I tried your code and it does indeed work with Shift and Click. You've taken a different approach to me.

I added the following code below yours (and commented out the SelectedIndexChanged lines) :-
C#:
            listBox.Click += (o, e) =>
            {
                var items = string.Join(",", listBox.SelectedItems.Cast<string>());
                this.Text = $"{listBox.SelectedItems.Count}: {items}";
            };

            void button1_Click(object sender, EventArgs e)
            {
                var items = string.Join(",", listBox.SelectedItems.Cast<string>());
                this.Text = $"{listBox.SelectedItems.Count}: {items}";
            }
This demonstrates the problem if you use the shift key with click to get multiple items.
I added a button to the form, which also shows the lines selected. The problem is still there.

It would seem that the Click event is not updating the selected items in the same way, although it does work with Click or Control Click.

It is not at all obvious to me as to why that should be the case. Still seems like a bug to me.

Update

I've changed my code back to use MultiExtended and changed the Click Event to the SelectedIndexChanged event, and it all seems to work as it should.
Thanks very much, and I'll have to bow to your superior knowledge on this.
It is still not clear why the Click Event does not work though.
 
Last edited:
Ah I see.

Anyway, it looks like it's tied up in the way WinForms tries to "rationalize" the Windows message events. If you are really interested, you could try debugging into the WinForms WM_MOUSEUP handler and LBN_SELCHANGE handler.
 
Ah I see.

Anyway, it looks like it's tied up in the way WinForms tries to "rationalize" the Windows message events. If you are really interested, you could try debugging into the WinForms WM_MOUSEUP handler and LBN_SELCHANGE handler.

No, I think I'll leave it at that and move on to the next problem. Done enough debugging of system code in my time.
 
SelectedIndexChanged is better suited. It would also work if you did a BeginInvoke from Click event, this would invoke right after Click event was handled and shows the timing issue of the windows messages in regard to selections.
 
Back
Top Bottom