为 UWP ComboBox 设置 SelectedItem

Set SelectedItem for UWP ComboBox

UWP ComboBox ItemsSource 显示正确,但未在列表中选择 SelectedItem。为什么会这样?

XAML:

<ComboBox Name="FooComboBox" 
    ItemsSource="{x:Bind ViewModel.Foos}" 
    SelectedItem="{x:Bind ViewModel.Foo,Mode=TwoWay,Converter={StaticResource ChangeTypeConverter}}"/>

ChangeTypeConverter 来自 Template10

Foos和属性的值Foo是在ViewModel

中设置的
public class ViewModel : ViewModelBase
{    
    Foo _Foo = default(Foo);
    public Foo Foo { get { return _Foo; } set { Set(ref _Foo, value); } }
    public ObservableCollection<Foo> Foos = new ObservableCollection<Foo>(FooService.GetFoos());
    public ViewModel()
    {
        Foo = FooService.GetDefaultFoo();

Foo 看起来像这样

public class Foo
{
    public Guid FooId { get; set; } = Guid.NewGuid();
    public string FooCode { get; set; }

    public override string ToString()
    {
        return FooCode;
    }
}

然而,尽管 FooComboBox 正确呈现了 Foos 的列表,SelectedItem 并未设置为 属性 Foo 的当前值。为什么会这样?

要将评论转化为答案,

SelectedItem 应该是 ItemsSource 列表中的实际项目,由 Equals() 方法确定。在您的情况下,它是一个单独的实例,尽管它具有相同的 ID,但不被视为相等。

有几种方法可以解决这个问题,也许将来可以解决类似问题的方法是覆盖 Equals:

public class Foo
{
    ...
    // untested
    public override bool Equals(object obj)
    {
        Foo other = obj as Foo;
        return FooId.Equals(other?.FooId);
    }
}

但这会对您应用的其余部分产生影响。当 Foo 是 ViewModel 时,我只会考虑使用它来解决 SelectedItem 问题。


另一种解决方案是在源列表中查找实际项目:

public ObservableCollection<Foo> Foos = ...;
public ViewModel()
{
   var d = FooService.GetDefaultFoo();
   Foo = Foos.FirstOrDefault(f => f.FooId == d.FooId);    
}