Home > OS >  Strange result when removing duplicated item from a WPF ListBox
Strange result when removing duplicated item from a WPF ListBox

Time:04-27

Here is my code:

public SelectorDemo()
{
    InitializeComponent();

    List<string> strs = new List<string>()
    {
        "AAAAAAAAAAAAAAAAAAAAA",
        "BBBBBBBBBBBBBBBBBBBBBBBB",
        "CCCCCCCCCCCCCCCCCCCCCCCC",
        "DDDDDDDDDDDDDDDDDDDDDDDD",
    };

    for (int i = 0; i < strs.Count; i  )
    {
        this.listBox1.Items.Add(strs[i]);
    }

    _ccc = strs[2];
    listBox1.Items.Insert(0, _ccc);
}

private void btn_Click(object sender, RoutedEventArgs e)
{
    listBox1.Items.Remove(0);
}

private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{

}    

You can see that my ListBox now has 5 items ("CC..","AA..","BB..","CC..","DD..") and I have a button which will remove any item.

If you select the 4th item (the second "CC..") then click the button that removes the item with index 0 (the first "CC.."), you will find that the ListBox.SelectionChanged event is not fired.

But, if you insert the second "CC.." just in front of the first one (which means the second "CC.."'s index is 2, the first "CC.."'s index is 3) then select first "CC." and click the button to remove the second "CC..", the ListBox.SelectionChanged event is fired.

It's so weird, can someone help me? I'm hoping the event is not fired in the second scenario.

CodePudding user response:

ListBox will not change the SelectedItems and not not fire SelectionChanged if currently selected item and the new one is equal by the object.Equals() method

The event fires because when an item is removed from the ListBox, it first decrements the index of the items whose index is greater than the index of the item being removed, and then checks "Did the selection change?". Indexes are also taken into account in this check.

In your case the index of the selected "CCC" is 3 and the index of the same unselected "CCC" is 2, when you remove the unselected "CCC", the ListBox remembers the index of the removed "CCC" when removing (2), then decrements all item indexes, which are greater than 2, the index of the selected "CCC" is now also 2, and when checking "is the selection changed?", the value of the selected item ("CCC") and its new index (2) are compared with the value of the removed item ("CCC" ) and the index of the removed item (2), the result of the comparison is true, and the ListBox fires SelectionChanged.

To avoid this wrap item with same content in ListBoxItem and add ListBoxItem to ListBox.Items:

    itemWithSameContent = strs[2];
    listBox1.Items.Insert(0, new ListBoxItem(){Content = itemWithSameContent});
  • Related