How do you bind a ComboBox's SelectedItem to a

2020-02-28 06:14发布

I'm using the MVVM pattern with WPF and have run into a problem, which 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 consumes 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 items on CardTypes and should preselect an item based on SelectedCardType.

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

For reasons outside of my control, the SelectedCardType object will be a reference-unequal copy of the item in CardTypes. Therefore WPF fails to match the SelectedItem to an item in ItemsSource, and when I run the app, the ComboBox initially appears with no item selected.

I tried overriding the Equals() and GetHashCode() methods on CardType, but WPF still fails to match the items.

Given my peculiar constraints, how can I get ComboBox to select the correct item?

3条回答
萌系小妹纸
2楼-- · 2020-02-28 06:36

You might not be overriding Equals and GetHashCode properly. This should work for you. (However, just overriding Equals will work in your case but it's considered to be good practice to override GetHashCode too 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();
    }
}
查看更多
迷人小祖宗
3楼-- · 2020-02-28 06:42

A workaround that you could do is to bind your SelectedItem to a string (instead of cardType), then create an object of type CardType using this string?

查看更多
够拽才男人
4楼-- · 2020-02-28 06:52

You can use SelectedValue and SelectedValuePath:

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

Where ProductId is a int property with NotifyPropertyChanged.

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

查看更多
登录 后发表回答