【问题标题】:How to preserve two way binded value when changing both datacontext and items source of WPF ComboBox更改 WPF ComboBox 的数据上下文和项目源时如何保留双向绑定值
【发布时间】:2020-05-23 13:36:39
【问题描述】:

背景

应用程序有一个绑定到“作业”列表的列表视图,其中的属性可由某些组合框编辑(具有两种方式绑定)。组合框的数据上下文通过列表视图的SelectionChanged 事件更改为当前选中的job

组合框值绑定到 Job 的一个属性。作业的itemssource 更改为与DataContextChanged 完全不同的列表。

Layout of widgets

问题

改变DataContext时,Job的combobox链接的绑定属性设置为null。

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

假设问题

我的这个假设可能不正确......

随着datacontext 的切换,旧选择的Job 或新选择的Job 设置为null,因为itemsource 不包含存储在新选择的或旧选择的@987654330 中的值@。

调试尝试(编辑)

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

问题

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

相关代码(删节 - 绑定到其他小部件按预期工作)

<ComboBox x:Name="ContactField" Grid.Column="1"  Grid.Row="3" Margin="2,1" Grid.ColumnSpan="3" DisplayMemberPath="Value" SelectedValuePath="Id" SelectedValue="{Binding Contact,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionChanged="ContactField_SelectionChanged"/>

代码隐藏 - 更改项目来源

private void UpdateCustomerDependancies() 
{

    imprintDataSetTableAdapters.CustomerContactsTableTableAdapter rpcdtta = new imprintDataSetTableAdapters.CustomerContactsTableTableAdapter();
    IList<ComboData> customers = new List<ComboData>();

    if (LeftFieldPanel.DataContext != null) //Where LeftFieldPanel contains all comboboxes
    {
        Job currentJob = (Job)LeftFieldPanel.DataContext;

        foreach (DataRow item in rpcdtta.GetDataBy(currentJob.CustomerCode).Rows)
        {
            customers.Add(new ComboData() { Id = item.ItemArray[0].ToString(), Value = item.ItemArray[1].ToString() });
        }
        ContactField.ItemsSource = customers;

    }
}

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

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

        }


    }

【问题讨论】:

  • 可以分享一下相关代码吗?你调试过代码吗?在调试过程中你注意到了什么?您尝试过什么方法来解决这个问题?
  • @ChetanRanpariya 我添加了代码上下​​文。已经总结了调试的结果,但是在这种情况下跟踪值的变化是相当具有挑战性的。解决问题的失败尝试包括破坏 MCV/MVVM 以覆盖组合框的文本值。无法达到所需的解决方案。
  • 根据this answer,您不能将SelectedItem 设置为ItemsSource 中未包含的内容(除非您将CombboBox.IsEditable 属性设置为true,在这种情况下用户可以在框中输入他们想要的任何内容)。
  • @KeithStein 根据我的努力和其他研究,我会同意。我正在开发一种解决方法,包括在绑定更改之前保存旧列表,然后删除任何不匹配的项目。它肯定不会很漂亮,但希望答案能帮助到这里的其他人。

标签: c# .net wpf data-binding combobox


【解决方案1】:

根据this answer 和我自己的研究,不可能简单地绑定并希望这是最好的。因此,我对此解决方案的工作方法如下。我已经概括了代码以使其适用于其他情况。

1) 在数据上下文发生变化时,将新项目追加到列表中,而不删除旧项目:

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
}

抱歉,如果这不够清楚,我觉得发布真正的代码会使脱离上下文的理解变得相当困难。

这解决了我自己的问题。

替代解决方案

见上文并添加项目而不删除旧项目。然后仅在 dropdownopened 事件上替换整个 itemssource。

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 2011-03-07
    相关资源
    最近更新 更多