集合重新填充后 WPF 组合框绑定中断

WPF Combobox Binding broken after Collection repopulation

我有以下情况。 我有一个 ListView 设置如下:

<ListView Margin="3,3,3,3" ItemsSource="{Binding Toner}" SelectedValue="{Binding CurrentToner}" IsSynchronizedWithCurrentItem="True">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="BorderBrush" Value="LightGray" />
                <Setter Property="BorderThickness" Value="0,0,0,1" />
            </Style>
        </ListView.ItemContainerStyle>

        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>

                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="50"></ColumnDefinition>
                        <ColumnDefinition Width="Auto"></ColumnDefinition>

                    </Grid.ColumnDefinitions>
                    <Label Grid.Row="0" Grid.Column="0" Content="{Binding Id}" FontWeight="Bold"></Label>
                    <Label Grid.Row="0" Grid.Column="1" Content="{Binding Name}" FontWeight="Bold"></Label>
                    <Label Grid.Row="1" Grid.Column="0" Content="{Binding Ratio}">
                    </Label>
                    <Label Grid.Row="1" Grid.Column="1" Content="{Binding TonerType.Name}"  ></Label>

                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

我在对应的ViewModel中设置了属性 CurrentToner:

private Toner currentToner = new Toner();
public Toner CurrentToner
    {
        get => currentToner;
        set
        {
            SetProperty(ref currentToner, value);
            updateTonerCommand.RaiseCanExecuteChanged();
            deleteTonerCommand.RaiseCanExecuteChanged();
            increaseAmountCommand.RaiseCanExecuteChanged();
            RaisePropertyChanged(nameof(Changes));
        }

    }

现在在与上面相同的视图中,我还有一些控件绑定到 CurrentToner 的属性。

<TextBox Style="{StaticResource TextBoxStyle}" Grid.Row="0" Grid.Column="1" Text="{Binding CurrentToner.Name}"></TextBox>
        <TextBox Style="{StaticResource TextBoxStyle}" Grid.Row="1" Grid.Column="1" Text="{Binding CurrentToner.Level}" ></TextBox>
        <ComboBox  Grid.Row="2" Grid.Column="1" SelectedValue="{Binding CurrentToner.TonerType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding TonerTypes, Mode=OneWay}" DisplayMemberPath="Name"></ComboBox>
        <TextBox Style="{StaticResource TextBoxStyle}" Grid.Column="1" Grid.Row="3" Text="{Binding CurrentToner.Note}" AcceptsReturn="True" VerticalScrollBarVisibility="Visible"></TextBox>

现在我可以在 ListView 中单击周围,我的 TextControls 将按预期更新。 但是,如果我重新加载 Observable 集合中的数据,则所选项目将不再在组合框中更新(数据仍然可用,我检查了调试器并且组合框仍然可以在 CurrentToner 中设置 TonerType) 我使用 Entity Framework 从 SQL 服务器重新加载数据:

private void ReloadToner()
    {
        Toner.Clear();
        using (var uw = new UnitOfWork(new Gritly_DEVEntities1()))
        {
            Toner.AddRange(uw.Toners.GetAll());

        }

    }

我必须如何实现我的重新加载逻辑才能再次更新所选项目? (它在重新加载之前有效)

编辑:屏幕截图展示了它应该是怎样的,而不是怎样的。 it should be like this not like this

EDIT2:我找到了答案,我不得不重写 TonerType 上的 Equals() 以根据 Id 而不是 Adress

进行比较

如果您重新加载数据,那么您的 collection 中就会有新的 object。
我错过了 object 类型的内容(如果它在那里的话),但我们无论如何都称其为碳粉。 确保碳粉具有唯一标识它的东西,例如 ID。 如果您查看 Toner object ,您可能可以算出哪个是旧的当前的,但计算机非常注重文字。他们需要您确切地告诉他们他们应该如何知道碳粉是一种特定的碳粉,而不仅仅是任何旧碳粉。

当您要 re-read 您的数据时,将该 ID 保存在私有变量中。 读取数据。
构建您的可观察对象 collection。 使用 id 上的一些 linq 匹配找到合适的条目。
类似于:

Toner newSelectedToner = Toners.Where(x=>x.ID = lastSelectedID).FirstOrDefault();

顺便说一下,这只是航空代码。 将 CurrentToner 设置为该实例。
此外,重写碳粉上的 equals 以使用 ID。