I would like my objects bound to ComboBox to be identified by Id instead of a reference. Is there anyway to do this in XAML without overriding Equals
and GetHashCode
?
Minimal example:
XAML:
<ComboBox
DisplayMemberPath="Name"
ItemsSource="{Binding People}"
SelectedValue="{Binding SelectedPerson}"
SelectedValuePath="Id" />
<Button
Height="32"
Click="ButtonBase_OnClick"
Content="Test assign" />
Code-behind:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
private Person _selectedPerson;
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public Person SelectedPerson
{
get => _selectedPerson;
set
{
_selectedPerson = value;
OnPropertyChanged(nameof(SelectedPerson));
}
}
public ObservableCollection<Person> People { get; set; } = new ObservableCollection<Person>
{
new Person { Id = 1, Name = "Angelina Jolie"},
new Person { Id = 2, Name = "Brad Pitt"}
};
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
SelectedPerson = new Person {Id = 1, Name = "Angelina Jolie"};
// SelectedPerson = People[0]; will work but i don't want that
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
As you can see I'm assigning SelectedPerson
to a new object but with the same Name and Id but it doesn't work. ComboBox still compares by reference.
In Vue and other frameworks, it's possible to specify a "key" used to identify objects while binding. v-bind:key
https://v2.vuejs.org/v2/guide/list.html
It works if you override Equals
: How do you bind a ComboBox's SelectedItem to an object that is a copy of an item from ItemsSource? but I wonder if there's any way to avoid that.
I was hoping SelectedValuePath
will do what I want but I was wrong, it just affects the return value of SelectedValue