WPF 组合框设置在项源更新后为 null

本文关键字:更新 null 组合 设置 WPF | 更新日期: 2023-09-27 18:01:00

我在WPF应用程序中使用ComboBox时遇到了困难。 它类似于其他一些问题,但这个问题的经典解决方案似乎不起作用。

本质上,这是与此相同的问题:

WPF 组合框选定项在选项卡控件开关上设置为 null

但是,我的 ItemsSource 已经在 SelectedItem 之后的 XAML 中,这通常是对此进行排序的。

正在发生的事情是,我有一个带有组合框的视图,上面已经加载了数据,然后触发了一个事件,该事件更新了馈送到 ComboBox 中的数据。 ViewModel 使用事件(由获取数据的 BackgroundWorker 触发(,并使用新数据更新其 ObservableCollection(即 ItemsSource(。 喜欢这个:

int id = (int)Invoice.Customer.DatabaseID;
Customers = new ObservableCollection<Customer>(customers);
Invoice.Customer = Customers.FirstOrDefault(x => x.DatabaseID == id);

如您所见,它尝试将发票上的客户设置回原来的状态。这确实会发生,观察到断点,但是,一旦完成,客户就会从未识别的源被设置回 null(我的代码都没有出现在调用堆栈中,都是框架的东西(。

组合框的 XAML 如下所示:

<ComboBox DisplayMemberPath="AccountCode"
    SelectedItem="{Binding Invoice.Customer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
    ItemsSource="{Binding Customers}"/>

总而言之,我的 ComboBox SelectedItem 在 ItemsSource 更新后被设置为 null,并确保 ItemsSource 在 SelectedItem 之后不执行任何操作。 我真的不知道为什么它被设置为空,我不确定在哪里看。 为了找到解决方案,我可以查看的任何指针或内容将不胜感激。

编辑:好的,我一直在玩它,我怀疑它与来自后台工作者的更新有关。 我在数据服务中使用计时器和后台辅助角色定期更新数据库中的客户列表,以确保数据相对最新。BackWorker 在完成后触发一个事件,以通知感兴趣的对象列表已更新。这似乎意味着当事件被使用时,它们位于不同的线程中。当它以这种方式更新时,在我将其设置为正确的项目后,选定项将设置为 null,因此将发票.客户设置为 null。 我快速向视图添加了一个按钮,以便在不使用 BackgroundWorker 的情况下更新客户,这似乎每次都有效。 我想定期更新数据,但我需要在这样做之前弄清楚这一点。

WPF 组合框设置在项源更新后为 null

好的,正如我在编辑中怀疑的那样,这与某种形式的线程有关。 在计时器启动更新后更新组合框项目源会导致它在更新到正确的客户后设置为 null。 我在一个新的应用程序中确认了这种行为,该应用程序中没有所有其他位,因此我可能会在我不打算的地方将其设置为 null(即使调用堆栈似乎严重暗示它不是我做的(。 当事件触发以更新结果时,与真实应用程序相比,我在新应用程序中得到了完全相同的调用堆栈。

在玩了

一番不同的东西之后,我遇到的方法(在我的新应用程序中 - 没有将其部署到真正的应用程序中,但手指交叉它也可以在那里工作!(是通过任务工厂运行竞争性更新触发事件(从这里的想法在我的 ViewModel 中使用调度程序是错误的吗?

在 ViewModel 中声明一个任务工厂:

TaskFactory uiFactory;

在你的构造函数中,像这样设置它:

uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());

然后,在数据更新后运行的事件中,执行以下操作:

private void AsyncMethods_TaskCompleted(object sender, EventArgs e)
{
    uiFactory.StartNew( () => UpdateResults());
}

在此上下文中,更新结果与更新发票上的客户相同。 它获取旧 ID,将 ItemsSource 设置为新集合,然后将绑定到 SelectedItem 的属性设置为新集合中的等效项。 这似乎有效,并没有给我以前遇到的奇怪行为。 我将它部署到实际的应用程序,并希望它也能在那里工作。 如果是这样,我会回来接受这个答案。

有时,

当您创建对象的"新"实例时,它可能会破坏您的绑定。可以在不调用"new"的情况下更新现有集合,也可以使可观察集合成为依赖项属性。

该问题是由这 2 行引起的。

Customers = new ObservableCollection<Customer>(customers);
Invoice.Customer = Customers.FirstOrDefault(x => x.DatabaseID == id);

您的组合框源已Customers,并且您正在再次初始化它。然后,您尝试从新初始化的成员中提取数据。新初始化的成员将不包含任何数据。

Customers里面没有数据。因此Invoice.Customer可能为空。

我不明白你为什么要初始化它并简单地尝试从中获取数据。您是否跳过以填充源?

如果您错过了填充源,请先用数据填充源。然后,您可以运行此代码而不再次初始化它,以便Invoice.Customer不为 null。

Invoice.Customer = Customers.FirstOrDefault(x => x.DatabaseID == id);