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

爱⌒轻易说出口 提交于 2019-12-13 21:12:01

问题


I have a ComboBox which has its ItemsSource bound to an ObservableCollection<CustomObject> where CustomObject has a few properties.

Sample class:

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 is bound to a CustomObject property which appears in a DataGrid row.

Sample class:

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

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

My objective is to load initial values into my DataGrid, but I do not know how to make the ComboBox realize that the CustomObject specified can be found in its ItemsSource, and consequently, the ComboBox does not render a SelectedItem.

Here 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");

Do you know how I make the ComboBox set its SelectedItem property like this? If I change my code so that DataGridEntry works only with string properties, then the ComboBox renders the SelectedItem after initializing as I expect. For reference types, it is not working though.


In case it is needed, this is how 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> contains an element which is instatiated the same as above: new CustomObject("val1", "val2", "val3");

I suspect that the ComboBox doesn't realize that the two CustomObjects are equivalent. And because of this suspicion, I overrode the Equals and GetHashCode functions for CustomObject, with no success. Apparently, the ComboBox has no problem detecting equality for non-reference data types such as strings. Thanks for the help! :)


回答1:


Bear in mind that GetHashCode() and Equals() work on Object type comparison (i.e. your ObservableCollection<T> would need to be for Object type. )

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




回答2:


The ComboBox is using Object.Equals to determine equality. By default, this means that the ComboBox expects identical references when working with reference types. When working with value types, Object.Equals compares the values. Although String is not technically a value type, it has overridden Object.Equals to compare values.

Similar to String, the equality behavior can be overridden by defining a custom Equals method for the class type the ComboBox holds.

For the example in the original post, 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 remain functional without it. It is a good idea to override Object.GetHashCode as well. This is out of the scope of this answer, however, a well documented implementation of this function can be found here:

What is the best algorithm for an overridden System.Object.GetHashCode?



来源:https://stackoverflow.com/questions/24767654/how-to-update-a-wpf-combobox-when-assigning-an-object-as-its-selecteditem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!