在 UWP 中,在列表视图数据模板中使用组合框时,selectedItem 丢失

In UWP, when using a combobox inside a listview datatemplate, selectedItem is lost

已经问了几个类似的问题,但我找不到任何看起来与我遇到的问题完全相同的问题。

我在 DataTemplate 中有一个 ComboBox 用于 ListViewComboBoxItemsSource 以及 SelectedItem 具有正确的绑定。我使用的模式与我在整个应用程序中使用的模式相同,没有任何问题。

无论出于何种原因,所选项目在途中某处被清空。我在所选项目中放置了断点,我可以看到它在列表构造期间被正确设置。然后,在呈现控件时,所选项目再次设置为 null(至少它是这样显示的)。当我在它被设置为 null 时查看调用堆栈时,堆栈仅显示我所在的行 [External Code].

作为参考,当前代码如下所示:

<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>

ComboBoxTypes 是一个 ObservableCollectionSelectedComboBoxType 是通过引用 RaceTypes.

中的一行来设置的

同样,正如我上面提到的,这种模式似乎在应用程序的其他任何地方都有效,但在 ListView.

中却无效

这是我用来填充列表项和组合框的代码示例。这不是实际代码,因为我无法提供实际代码。尽管它说明了正在采取的步骤,但它已经足够接近了。

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

当您颠倒 select code-behind 中某项的顺序时,通常会发生这种情况。考虑以下两个选项:

选项 1

SelectedComboBoxType = items[0];
ComboBoxTypes = items;

选项 2

ComboBoxTypes = items;
SelectedComboBoxType = items[0];

选项 1 中,您首先设置 selected 项目,它会导致更改通知,该通知会立即由控件处理。然而,该控件尚未绑定到 items,因此不会将 SelectedItem 设置为您的 selection,但相反会导致更新回 SelectedComboBoxType 之前的 selected 值。

基本上这意味着您总是可以 select 只有 您想要 select 的值已经绑定到控件之后。 选项 2 应该可以解决您的问题。

我从 Microsoft Developer Network 收到了一些可行的答案,所以我想我会在这里与 运行 遇到同样问题的任何人分享它们。

选项 1 如果值为 null,则对 setter 进行测试以绕过更新支持字段。

这对我来说是一个 hack,但它工作得很好。

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

选项 2 将 SelectedItem 上的绑定从 x:Bind 更改为 Binding.

<ComboBox 
    ItemsSource="{x:Bind ComboBoxTypes, Mode=OneWay}"
    SelectedItem="{Binding SelectedComboBoxType, Mode=TwoWay, Converter={StaticResource GenericConverter}}"
    DisplayMemberPath="Name"/>

令人失望的是,解决方案是使用旧的编码风格,但它也解决了这个问题,而无需在代码中添加额外的 null-test-bypass 选项。

Here is a link to the original answer provided to me