簡體   English   中英

ItemsSource更新后,WPF ComboBox設置為null

[英]WPF ComboBox setting to null after ItemsSource updated

我在WPF應用程序中與ComboBox掙扎。 它與其他一些問題類似,但是經典的解決方案似乎無效。

本質上,這是相同的問題:

WPF ComboBox SelectedItem在TabControl開關上設置為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(我的代碼都沒有出現在調用堆棧中,這全是框架內容)。

ComboBox的XAML是這樣的:

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

綜上所述,我的ComboBox SelectedItem在ItemsSource更新后設置為null,並確保ItemsSource在SelectedItem之后什么也不做。 我真的不知道為什么將其設置為null,我不確定在哪里看。 為了找到解決方案,我可以看任何指針或事物,將不勝感激。

編輯:好的,我一直在玩它,我懷疑它與BackgroundWorker的更新有關。 我在數據服務中使用Timer和BackgroundWorker定期從數據庫更新客戶列表,以確保數據相對最新。 當它完成通知相關對象該列表已更新時,BackgroundWorker將觸發一個事件。 這似乎意味着當事件被消耗時,它們位於不同的線程中。 當它以這種方式更新時,在我將SelectedItem設置為正確的項目之后,將SelectedItem設置為null,因此將Invoice.Customer設置為null。 我迅速在視圖中添加了一個按鈕,以在不使用BackgroundWorker的情況下更新客戶,這似乎每次都起作用。 我想定期更新數據,但需要先弄清楚這一點,然后再進行操作。

好的,正如我在編輯中所懷疑的那樣,這與某種形式的線程化有關。 從計時器啟動更新后開始更新ComboBox ItemsSource,導致將其更新為正確的客戶后將其設置為null。 我在一個沒有其他所有內容的新應用程序中確認了此行為,因此有可能我將它設置為null,而這並不是我本來想要的(即使調用堆棧似乎在很大程度上暗示它不是我)正在做)。 當事件觸發以更新結果時,與真實應用程序相比,新應用程序中的調用堆棧看起來完全相同。

經過一番嘗試之后,我遇到的方法(在我的新應用程序中-尚未將其部署到實際的應用程序中,但是手指也在那里工作了!)是通過競爭性更新觸發事件一個TaskFactory(從這里開始的想法在我的ViewModel中使用Dispatcher是錯誤的嗎? )。

在ViewModel中聲明一個TaskFactory:

TaskFactory uiFactory;

在您的構造函數中將其設置如下:

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

然后,在數據更新后運行的情況下,執行以下操作:

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

在這種情況下,UpdateResults與更新發票上的客戶相同。 它獲取舊ID,將ItemsSource設置為新集合,然后將綁定到SelectedItem的屬性設置為新集合中的等效項。 這似乎在起作用,並且沒有給我以前的古怪行為。 我打算將其部署到實際的應用程序中,並希望它在那里也能正常工作。 如果可以,我會回來接受這個答案。

有時,當您創建對象的“新”實例時,它可能會破壞您的綁定。 您可以在不調用“ new”的情況下更新現有Collection,也可以將ObservableCollection設置為依賴項屬性。

問題是由這兩行引起的。

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

您的組合框來源是“ Customers並且您要再次對其進行初始化。 然后,您嘗試從新初始化的成員中獲取數據。 新初始化的成員中將沒有數據。

Customers中沒有數據。 因此Invoice.Customer可能為空。

我不明白為什么要初始化它,而只是嘗試從中獲取數據。 您跳過填充源了嗎?

如果錯過了填充源,請先用數據填充源。 然后,您可以運行此代碼而無需再次對其進行初始化,以使Invoice.Customer不為空。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM