How to update ComboBox WPF when assigning an object as SelectedItem?

I have a ComboBox that has an ItemsSource associated with an ObservableCollection<CustomObject> , where CustomObject has several properties.

Class Example:

 public class CustomObject : INotifyPropertyChanged { public string Property1 { /*...omitted for brevity...*/ } public string Property2 { /*...omitted for brevity...*/ } public string Property3 { /*...omitted for brevity...*/ } } 

The SelectedItem property of my ComboBox tied to the CustomObject property that appears in the DataGrid row.

Class Example:

 public class DataGridEntry : INotifyPropertyChanged { public CustomObject Column1 { /*...omitted for brevity...*/ } public string Column2 { /*...omitted for brevity...*/ } public string Column3 { /*...omitted for brevity...*/ } } 

I create an ObservableCollection<CustomObject> during the initialization of my window, and then set the data context of my DataGrid to an ObservableCollection<DataGridEntry> .

My task is to load the initial values ​​into my DataGrid , but I do not know how to make the ComboBox clear that the specified CustomObject can be found in its ItemsSource , and therefore, ComboBox > does not display a SelectedItem .

This is how I load the initial values:

 ObservableCollection<DataGridEntry> entries = new ObservableCollection<DataGridEntry>(); MyWindow.DataContext = this; entries.Add(new DataGridEntry(new CustomObject("val1", "val2", "val3"), "col2", "col3"); 

Did you know that I set the ComboBox its SelectedItem property as follows? If I change my code so that the DataGridEntry only works with string properties, then the ComboBox displays the SelectedItem after initialization, as I expect. For reference types, it does not work.


If necessary, I bind the data to the ComboBox :
 <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CustomObjectsCollection}" SelectedItem="{Binding Column1, UpdateSourceTrigger=PropertyChanged}"/> 

EDIT:
In case it is not clear, the ObservableCollection<CustomObject> element contains an element that is set in the same way as above: new CustomObject("val1", "val2", "val3");

I suspect that the ComboBox does not understand that the two CustomObjects equivalent. And because of this suspicion, I overridden the Equals and GetHashCode functions for CustomObject , without any success. There seems to be no problem in ComboBox finding equality for nonreferenced data types such as strings. Thanks for the help!:)

0
source share
2 answers

ComboBox uses Object.Equals to determine equality. By default, this means that the ComboBox expects identical links when working with reference types. When working with value values, Object.Equals compares values. Although String not technically a value type, it overrides Object.Equals to compare values.

Like String , equality behavior can be overridden by defining a custom Equals method for a class type that has a ComboBox .

For example, in the original message, the Equals method should compare each property as such:

 public class CustomObject : INotifyPropertyChanged { //Include properties, constructor, and INotifyPropertyChanged interface members. public override bool Equals(object obj) { CustomObject test = obj as CustomObject; //test=null if obj cannot be casted. if(test == null) return false; //Comparing null against non-null: FALSE else { //Check if all properties are equal. return ((Property1.CompareTo(test.Property1) == 0) && (Property2.CompareTo(test.Property2) == 0) && (Property3.CompareTo(test.Property3) == 0)); } } } 

Although the ComboBox will be left without it. It is also recommended to override Object.GetHashCode . This is beyond the scope of this answer, however a well-described implementation of this function can be found here:

What is the best algorithm for overriding System.Object.GetHashCode?

0
source

Keep in mind that GetHashCode() and Equals() work when comparing an Object type (i.e. your ObservableCollection<T> should be for an Object type.)

For a stronger typed override, you must implement IEquatable<T> - this should allow combobox to compare items when setting the SelectedItem property.

+3
source

Source: https://habr.com/ru/post/1237597/


All Articles