C# 如何在更改WPF ComboBox的datacontext和items源时保留双向绑定值

C# 如何在更改WPF ComboBox的datacontext和items源时保留双向绑定值,c#,.net,wpf,data-binding,combobox,C#,.net,Wpf,Data Binding,Combobox,背景 应用程序有一个绑定到作业列表的列表视图,其中的属性可以通过一些具有双向绑定的组合框进行编辑。组合框的数据上下文通过列表视图的SelectionChanged事件更改为当前选定的作业 combobox值绑定到Job的属性。DataContextChanged后,作业的itemssource将更改为完全不同的列表 发行 更改DataContext时,链接到作业组合框的绑定属性设置为null 通过单击作业列表,绑定到任何组合框的所有属性都设置为null 假定问题 我的这个假设可能不正确 切换da

背景

应用程序有一个绑定到作业列表的列表视图,其中的属性可以通过一些具有双向绑定的组合框进行编辑。组合框的数据上下文通过列表视图的SelectionChanged事件更改为当前选定的作业

combobox值绑定到Job的属性。DataContextChanged后,作业的itemssource将更改为完全不同的列表

发行

更改DataContext时,链接到作业组合框的绑定属性设置为null

通过单击作业列表,绑定到任何组合框的所有属性都设置为null

假定问题

我的这个假设可能不正确

切换datacontext时,旧选定作业或新选定作业将设置为null,因为itemsource不包含存储在新选定作业或旧选定作业上的值

调试尝试编辑

我注意到,在更改作业列表的SelectedItem之前,作业属性的值被设置为null

问题:

将ComboBox的datacontext切换到不包含SelectedValue的itemsource时,如何保留Job的Bind属性的值

相关代码节略-绑定到其他小部件的效果与预期一样

代码隐藏-更改项目源

代码隐藏-更改数据上下文

根据我自己的研究,不可能简单地绑定并希望达到最佳状态。因此,我对此解决方案的工作如下。我已概括了该守则,使其适用于其他情况

1更改datacontext后,将新项目追加到列表中,而不删除旧项目:

private void ListView1_SelectedItemChanged(...) {
    List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList(); 
    //Add new items to comboitems here
    ComboBox1.ItemsSource = comboitems; //Rebind
}
2打开组合框下拉列表后,获取itemsource并仅删除旧项目

private void ComboBox1_DropDownOpened(...) {
    List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList(); 
    //Remove old items from comboitems here
    ComboBox1.ItemsSource = comboitems; //Rebind
}
抱歉,如果这还不够清楚,我觉得发布真正的代码会使理解脱离上下文变得相当困难

这解决了我自己的问题

替代溶液


请参见上文,添加项目而不删除旧项目。然后仅在DropDownOpen事件中替换整个itemssource。

您可以共享相关代码吗?你调试代码了吗?调试期间您注意到了什么?你试图用什么方法来解决这个问题?@ChetanRanpariya我添加了代码上下文。调试结果已经总结,但是在这种情况下跟踪值的变化是相当具有挑战性的。解决问题的失败尝试包括中断MCV/MVVM以覆盖组合框的文本值。无法达到所需的解决方案。根据,您不能将SelectedItem设置为ItemsSource中不包含的内容,除非您将ComboBox.IsEditable属性设置为true,在这种情况下,用户可以在框中输入任何他们想要的内容。@KeithStein根据我的努力和其他研究,我同意您的看法。我正在开发一种变通方法,包括在绑定更改之前保存旧列表,然后删除任何不匹配的项。这当然不会很好,但希望答案能帮助其他人。
private void jobTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (jobTree.SelectedItem.GetType() == typeof(Job))
        {
            DelGrid.Visibility = Visibility.Hidden;


            Job j = (Job)jobTree.SelectedItem;


            MessageBox.Show(j.Contact);

            LeftFieldPanel.DataContext = j; //Switch datacontext
            RightFieldPanel.DataContext = j; //switchdata context

        }


    }
private void ListView1_SelectedItemChanged(...) {
    List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList(); 
    //Add new items to comboitems here
    ComboBox1.ItemsSource = comboitems; //Rebind
}
private void ComboBox1_DropDownOpened(...) {
    List<ComboData> comboitems = ((IList<ComboData>)ComboBox1.ItemsSource).ToList(); 
    //Remove old items from comboitems here
    ComboBox1.ItemsSource = comboitems; //Rebind
}