A UWP ComboBox ItemsSource displays correctly but the SelectedItem is not selected in the list. Why is that so?
The XAML:
<ComboBox Name="FooComboBox"
ItemsSource="{x:Bind ViewModel.Foos}"
SelectedItem="{x:Bind ViewModel.Foo,Mode=TwoWay,Converter={StaticResource ChangeTypeConverter}}"/>
ChangeTypeConverter
comes from Template10
Foos
and the value of the property Foo
are set in the 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();
A Foo looks like this
public class Foo
{
public Guid FooId { get; set; } = Guid.NewGuid();
public string FooCode { get; set; }
public override string ToString()
{
return FooCode;
}
}
Yet although FooComboBox
correctly renders the list of Foos
, the SelectedItem
is not set to the current value of the property Foo
. Why is that so?
To turn the comments into an answer,
The SelectedItem should be an actual item inside the ItemsSource list, as determined by the Equals() method. In your case it was a separate instance and although it had the same Id it wasn't considered Equal.
There are several ways to solve this, perhaps the one that will solve similar issues down the road is to override Equals:
public class Foo
{
...
// untested
public override bool Equals(object obj)
{
Foo other = obj as Foo;
return FooId.Equals(other?.FooId);
}
}
but this has implications for the rest of your app. I would only consider using this to solve a SelectedItem issue when Foo is a ViewModel.
The other solution is to go find the actual item in the source list:
public ObservableCollection<Foo> Foos = ...;
public ViewModel()
{
var d = FooService.GetDefaultFoo();
Foo = Foos.FirstOrDefault(f => f.FooId == d.FooId);
}