WPF: Combobox will lose the selected index after related changes to the ItemSource collection

I searched Google and here for answers, my problem is somewhat related to the question below, but different enough to guarantee a new question.

Combo-box loses choice after collection changes

Basically, I have a WPF combo box associated with the ObservableCollection class. This class has additional functionality to postpone collection change notifications if I need to make a few changes, for example, clear and replenish it to get a fresh snapshot of the database.

My combobox binding has both DisplayMemberPath and SelectedValuePath. Highlighting SelectedValuePath enables the integer property.

The problem is the same as the mentioned question, when I update the values ​​in the linked collection, the linked ComboBox loses its choice and is empty (SelectedIndex = -1).

I can confirm that the CollectionChanged event is not triggered until the collection is re-populated and returns items to it.

More puzzling if I do the following:

using (_collection.DelayNotifications()) { var items = _collection.ToArray(); _collection.Clear(); _collection.AddRange(items); } 

Combobox does not lose its selected value.

Which means that it breaks if the elements of the collection are replaced with new elements obtained from the database - I could accept this if I did not use the SelectedValuePath binding, but because I exist, and because the integer values ​​are the same the most, of course, what am I doing should work?

I am using .NET 3.5 SP1

Does anyone have any idea?

Edit

From the comments below and Blam’s answer. I agree that these are the reasons why this is being done. But it really doesn’t help me.

I am binding the SelectedValue property of the Combobox property to the Integer property in my view model. If I had to bind SelectedItem, I would need to bind a property of this object type to my view model, but this is an integer property, which I actually post on.

At the moment, I have "fixed" (read a minor hack) a problem related to the forced change of the property event for the "SelectedValue" property. It appears that Combobox is double-checking its internal list for an element that matches a specific SelectedValuePath element.

The WPF combination should “know” that it has a value of SelectedValuePath, so I don't think it's too far from this jump to suggest that it will adjust the element's matching logic. However, this goes beyond the scope of the SO.

I understand that, probably, I just agree that this is exactly how WPF works, but after several years of struggling with data combos in WinForms, I kind of hoped that I would not have to with WPF :) - although speaking that combinatorial combinations of WPF are much better than WinForm.

+7
c # data-binding wpf combobox
source share
1 answer

This statement is incorrect.

I could accept this if I hadn't used the SelectedValuePath binding, but because I

You are not attached to SelectedValuePath.
You are attached to a collection of objects.
SelectedValuePath for reporting only has nothing to do with matching objects for equality. DisplayMemberPath for reporting only has nothing to do with matching objects for equality.

You confuse SelectValuePath with SelectedItem.
ComboBox does not use SelectedValuePath to determine whether two objects are equal.

From the documentation for SelectedValuePath:

Gets or sets the path that is used to get SelectedValue from SelectedItem.

In the example that bothers you, you are loading the same objects again.

I'm going to assume that SelectedValuePath is a property named ID

If you clear and recreate an object with identifier 6, it will not equal the cleared object with identifier 6.

Try it. Create two objects (o1 and o2) with identifier 6 and compare o1.Equals (o2).

If you want the two objects with identifier 6 to be equal, you need to override GetHashCode and Equals. Equals returns true if both have identifier 6. And you can use ID as GetHashCode.

A string is a reference type that will deceive you. string s1 = "cat",
string s2 = "cat",
s1.Equals (s2) will return true, since String Equals is overridden to compare values.

+4
source share

All Articles