2016-08-04 69 views
0

我有一個與WPF應用程序中的ComboBox鬥爭。它類似於其他一些問題,但是這個問題的經典解決方案似乎沒有工作。WPF組合框設置爲null後ItemsSource更新

從本質上講,這是同樣的問題,因爲這:

WPF ComboBox SelectedItem Set to Null on TabControl Switch

然而,我的ItemsSource已經在以後的SelectedItem的XAML,這是正常排序了這一點。

發生了什麼事情是我有一個視圖,其上已經裝載了數據的組合框,然後觸發一個事件來更新輸入到組合框中的數據。 ViewModel使用事件(由獲取數據的BackgroundWorker觸發)並使用新數據更新其作爲ItemsSource的ObservableCollection。像這樣:

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}"/> 

所以總結一下,我的組合框的SelectedItem被設置爲NULL的ItemsSource更新完畢後,並確保的ItemsSource是的SelectedItem什麼都不做了。我真的不知道爲什麼它被設置爲空,我不知道在哪裏看。任何指針或事情,我可以看看,以找到解決辦法,將不勝感激。

編輯:好的,我一直在玩它多一點,我懷疑它與來自BackgroundWorker的更新有關。我在我的數據服務中使用Timer和BackgroundWorker來定期更新數據庫中的客戶列表,以確保數據相對最新。 BackgroundWorker在完成時觸發事件以通知感興趣的對象該列表已更新。這似乎意味着,當事件消耗時,它們處於不同的線程中。當它以這種方式更新時,SelectedItem在我將其設置爲正確的項目並因此將Invoice.Customer設置爲null後被設置爲null。我很快在視圖中添加了一個按鈕,以便在不使用BackgroundWorker的情況下更新客戶,這似乎每次都有效。我想定期更新數據,但我必須先弄清楚這一點,然後才能做到這一點。

+0

我更新了我的ItemsSource,並且我的SelectedItem保持它應該在的位置。不能重現你的問題。顯示Invoice.Customer屬性的定義。 – AnjumSKhan

回答

-1

好的,正如我在編輯中所懷疑的,這是以某種方式進行線程處理的。在更新被定時器啓動後更新組合框ItemsSource會導致它在更新到正確的Customer後設置爲空。我在一個新的應用程序中證實了這種行爲,它沒有其他所有的位,因此我可能會將它設置爲null,我不打算這樣做(儘管調用堆棧似乎嚴重暗示它不是我正在做)。當事件觸發以更新結果時,我看到了新應用中與真實應用相比完全相同的調用堆棧。

經過一些玩弄不同的東西后,我找到了一種方法(在我的新應用程序中 - 沒有將它部署到真正的應用程序,但手指越過它也在那裏工作!)是要由事件通過TaskFactory運行競爭更新(這裏的想法Is it wrong to use the Dispatcher within my ViewModel?)。

在視圖模型聲明TaskFactory:

TaskFactory uiFactory; 

在構造函數中設置它是這樣的:

uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()); 
在運行中的數據已經更新做這樣的事情後,事件

然後:

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

而且UpdateResults在這方面是一樣的更新T上的客戶他發票。它獲取舊ID,將ItemsSource設置爲新集合,然後將綁定到SelectedItem的屬性設置爲新集合中的等效項目。這似乎是工作,並沒有給我我以前有過的奇怪行爲。我將把它部署到實際的應用程序,並希望它也能在那裏工作。如果是這樣,我會回來接受這個答案。

-1

有時,當您創建Object的「新」實例時,它可能會破壞綁定。您可以更新現有Collection而不調用「new」,或者可以使ObservableCollection成爲依賴項屬性。

-1

這個問題是由這兩行引起的。

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

你的組合框源是Customers和你再次對其進行初始化。然後,您嘗試從新初始化的成員獲取數據。新初始化的成員將沒有數據。

ie Customers裏面沒有數據。因此Invoice.Customer可能會爲空。

我不明白你爲什麼初始化它,只是試圖從中獲取數據。你是否跳過填寫源代碼?

如果您錯過了填寫來源,請先填寫數據來源。然後,您可以運行此代碼而無需再次初始化,以使Invoice.Customer不爲空。

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

來源已滿。我可能沒有很好地解釋這一點,但我在Invoice.Customer集上劃了一個斷點。它按照預期設置客戶(來自Invoice.Customer = ...),但隨後它被設置爲null,我認爲它是框架中的東西,因爲堆棧跟蹤只有外部代碼。 – Tominator

+0

框架如何設置它?不可能。一個屬性永遠不能是這樣的null。也許你在代碼本身的某個地方設置爲null。 – ViVi

+0

如果你把ItemsSource放在XAML中的SelectedItem之前,那麼它可以把它自己設置爲null,就像我鏈接的問題一樣。我還沒有做到這一點,但我仍然把我的SelectedItem設置爲空,它不是我能找到的代碼中的任何地方。 – Tominator

相關問題