There have been several similar questions asked, but I couldn't find anything that looked to be exactly the same as what I'm experiencing.
I've got a ComboBox
inside a DataTemplate
for a ListView
. The ComboBox
has the correct bindings to the ItemsSource
as well as the SelectedItem
. The pattern I'm using is the same pattern I use throughout the application without any problems.
For whatever reason though, the selected item is getting nulled out somewhere along the way. I've put breakpoints inside the selected item and I can see that it is being properly set during the lists construction. Then, the selected item is being set again to null
while the control is being rendered (at least that's the way it appears). When I look at the call stack at the point it's being set to null
, the stack only shows the line I'm on [External Code]
.
For reference, here is what the current code looks like:
<ListView ItemsSource="{x:Bind Vm.ListVms, Mode=OneWay}"
SelectedItem="{x:Bind Vm.SelectedListVm, Mode=TwoWay, Converter={StaticResource GenericConverter}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="ListItemVm">
<StackPanel Orientation="Horizontal">
<ComboBox
ItemsSource="{x:Bind ComboBoxTypes, Mode=OneWay}"
SelectedItem="{x:Bind SelectedComboBoxType, Mode=TwoWay, Converter={StaticResource GenericConverter}}"
DisplayMemberPath="Name"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
The ComboBoxTypes
is an ObservableCollection
.
SelectedComboBoxType
is set by referencing a row from the RaceTypes
.
Again, as I mentioned above, this pattern that seems to work everywhere else in the application, but not inside a ListView
.
Here is a sample of what the code looks like that I'm using to populate the list items and the combo boxes. It's not actual code, because I can't provide the actual code. It is close enough though that it illustrate the steps being taken.
vm.ListVms.Clear();
foreach (var unit in source.ListItems)
{
var listVm = new ListVm();
listVm.ComboBoxTypes.Add();
listVm.ComboBoxTypes.Add();
listVm.ComboBoxTypes.Add();
listVm.ComboBoxTypes.Add();
listVm.SelectedComboBoxType = listVm.ComboBoxTypes.FirstOrDefault(r => r.Id == (int) unit.ComboBoxType);
vm.ListVms.Add(listVm);
}
I received a couple of workable answers from the Microsoft Developer Network, so I thought I would share them here for anybody who has run into this same problem.
Option 1 Put in a test on the setter to bypass updating the backing field if the value is null.
This is a hack to me, but it works perfectly.
public ComboboxItemVm SelectedComboBoxType
{
get { return selectedType; }
set
{
if (value == null)
{
Debug.WriteLine("null!");
return;
}
if (value != selectedType)
{
selectedType = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedComboBoxType"));
}
}
}
Option 2 Change the binding on the SelectedItem from x:Bind to Binding.
<ComboBox
ItemsSource="{x:Bind ComboBoxTypes, Mode=OneWay}"
SelectedItem="{Binding SelectedComboBoxType, Mode=TwoWay, Converter={StaticResource GenericConverter}}"
DisplayMemberPath="Name"/>
It's disappointing that the solution is to use an older coding style, but it also fixes the issue without having to add an extra null-test-bypass option in the code.