Wpf 如何将组合框的SelectedItem绑定到作为ItemsSource中项目副本的对象?

Wpf 如何将组合框的SelectedItem绑定到作为ItemsSource中项目副本的对象?,wpf,xaml,mvvm,data-binding,combobox,Wpf,Xaml,Mvvm,Data Binding,Combobox,我在WPF中使用MVVM模式,遇到了一个问题,我可以将其简化为以下内容: 我有一个卡片式的模型 public class CardType { public int Id { get; set; } public string Name { get; set; } } 我有一个使用CardType的viewmodel public class ViewModel : INotifyPropertyChanged { private CardType selectedCa

我在WPF中使用MVVM模式,遇到了一个问题,我可以将其简化为以下内容:

我有一个卡片式的模型

public class CardType
{
    public int Id { get; set; }
    public string Name { get; set; }
}
我有一个使用CardType的viewmodel

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 ...
}
我的XAML有一个组合框,它的项目基于CardType,并且应该根据SelectedCardType预先选择一个项目

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 ...
}
<ComboBox ItemsSource="{Binding CardTypes}"
          DisplayMemberPath="Name"
          SelectedItem="{Binding SelectedCardType}"/>
由于我无法控制的原因,SelectedCardType对象将是CardTypes中项目的引用副本。因此,WPF无法将SelectedItem与ItemsSource中的项目匹配,并且当我运行应用程序时,组合框最初会显示,但未选择任何项目

我尝试在CardType上重写Equals和GetHashCode方法,但WPF仍然无法匹配这些项


鉴于我的特殊限制,如何让ComboBox选择正确的项目?

一种解决方法是将SelectedItem绑定到字符串而不是cardType,然后使用此字符串创建cardType类型的对象?

您可以使用SelectedValue和SelectedValuePath:

<ComboBox ItemsSource="{Binding CardTypes}"
          DisplayMemberPath="Name"
          SelectedValue="{Binding ProductId, Mode=TwoWay}" 
          SelectedValuePath="Id"/>
其中ProductId是NotifyPropertyChanged的int属性

请在此处阅读一个很好的解释:

您可能没有正确覆盖Equals和GetHashCode。这应该对你有用。然而,在您的情况下,只重写Equals是可行的,但是当您为类重写Equals时,重写GetHashCode也是一种好的做法

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();
    }
}

这需要我将viewmodel的SelectedCardType属性更改为整数,但我无法自由执行此操作。好的,可以肯定,使用此方法,您至少需要添加一个整数。我很快在小样本中进行了尝试,效果非常好。您可以添加如何从代码中设置SelectedCardType的代码吗?Id.GetHashCode可以被替换为Id。虽然最热门的答案有效,但这:是解决同一问题的更优雅的方法。