How do you bind a ComboBox SelectedItem to an object that is a copy of an item from an ItemsSource?

I am using the MVVM template with WPF and have encountered a problem that I can simplify to the following:

I have a CardType model.

public class CardType { public int Id { get; set; } public string Name { get; set; } } 

And I have a viewmodel that uses CardType.

 public class ViewModel : INotifyPropertyChanged { private CardType selectedCardType; public CardType SelectedCardType { get { return selectedCardType; } set { selectedCardType = value; OnPropertyChanged(nameof(SelectedCardType)); } } public IEnumerable<CardType> CardTypes { get; set; } // ... and so on ... } 

My XAML has a ComboBox that bases its elements on CardTypes and must first select an element based on SelectedCardType.

 <ComboBox ItemsSource="{Binding CardTypes}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedCardType}"/> 

For reasons beyond my control, the SelectedCardType object will be an unequal copy reference of an element in CardTypes. So WPF cannot match SelectedItem with an item in ItemsSource, and when I launch the application, ComboBox initially appears without a selected item.

I tried to override the Equals () and GetHashCode () methods in CardType, but WPF still does not match the elements.

Given my particular limitations, how can I get ComboBox to select the correct item?

+5
source share
3 answers

You may not be able to override Equals and GetHashCode correctly. This should work for you. (However, only overriding Equals will work in your case, but it is considered good practice to override GetHashCode when you override Equals for a class)

 public class CardType { public int Id { get; set; } public string Name { get; set; } public override bool Equals(object obj) { CardType cardType = obj as CardType; return cardType.Id == Id && cardType.Name == Name; } public override int GetHashCode() { return Id.GetHashCode() & Name.GetHashCode(); } } 
+5
source

You can use SelectedValue and SelectedValuePath:

 <ComboBox ItemsSource="{Binding CardTypes}" DisplayMemberPath="Name" SelectedValue="{Binding ProductId, Mode=TwoWay}" SelectedValuePath="Id"/> 

Where ProductId is an int property with NotifyPropertyChanged.

Read a great explanation here: The difference between SelectedItem, SelectedValue and SelectedValuePath

+4
source

The workaround you can do is to bind your SelectedItem to a string (instead of cardType) and then create an object of type CardType using that string?

0
source

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


All Articles