![](/img/trans.png)
[英]Update an ObservableCollection with a background worker in MVVM
[英]Update ObservableCollection from background Worker
我有一個DatGrid,它綁定到var Result_Full = new ObservableCollection<IP_DataRow>()
。 這是一個包含多個字符串和雙變量的簡單類。 沒什么難的。
我所做的是,我讀了一個Excel文件(使用Telerik RadSpreadProcessing),它將行解析到我的類中。 我在一個線程上執行此操作,以便不阻止UI。 我遇到了一些問題:
1)我不能在讀取excel文件的長進程中使用ref
關鍵字(因為Result_Full是綁定到DataGrid的公共屬性),但我必須創建臨時ObservableCollection<IP_DataRow>()
,其中放置值。 完成該過程后,我運行以下腳本來復制值:
foreach (var item in tmpFull)
{
InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
我想做的是,能夠實時查看(如果可能)如何將項目添加到我的DataGrid中的集合中。
當我使用.Net 4.5時,我嘗試按照其他帖子的建議實現BindingOperations.EnableCollectionSynchronization
,但我無法弄清楚如何將我的UI模型集合Result_Full綁定到進程中臨時使用的。
2)即使使用當前設置,當我(在我的UI下)移動到包含DataGrid的我的Tab(我的DataGrid在不同的TabPage上)時,我嘗試使用上面提到的代碼將新項添加到集合中,它返回錯誤說: 調用線程無法訪問此對象,因為另一個線程擁有它。 ,這是相當奇怪的,因為InvokeOnUIThread只是Dispatcher.Invoke()
,它應該是線程安全的?
任何幫助將受到高度贊賞。
編輯:顯示更多代碼:
這是我從BackgroundWorker調用的過程:
public void ProcessFile()
{
var tmpError = new ObservableCollection<IP_DataRow>();
var tmpFull = new ObservableCollection<IP_DataRow>();
var _reader = new IP_ExcelReader(sExcelPath, ref tmpError, ref tmpFull);
string sResult = _reader.ReadExcelFile();
if (sResult != string.Empty)
{
System.Windows.MessageBox.Show("Error processing selected Excel File!" + Environment.NewLine + Environment.NewLine + "Error message:" + Environment.NewLine + sResult);
}
foreach (var item in tmpError)//populates error list
{
IP_InvokeOnUIThread(() =>
{
Result_Error.Add(item);
});
}
foreach (var item in tmpFull)//populates full list
{
IP_InvokeOnUIThread(() =>
{
Result_Full.Add(item);
});
}
OnPropertyChanged("Result_Full");
//OnPropertyChanged("Result_Error");
iSelectedTabIndex = 1;
}
在這里你可以看到,我必須創建臨時集合tmpError,tmpFull ,我收集我的數據。 在進程結束時,我手動將值復制到綁定到DataGrid的主集合中。 我想改變這一點,這意味着在過程中將值復制到主集合(而不是臨時集合),以便用戶可以實時查看如何將值添加到集合中。
PS2:由於我的原因,我的InvokeOnUIThread
調用中存在一個問題。 一旦我從App.Current.Dispatcher.Invoke(action);
改變了App.Current.Dispatcher.Invoke(action);
到App.Current.Dispatcher.BeginInvoke(action);
錯誤與..different線程擁有它停止。
Application.Current.Dispatcher
簡而言之,我相信你應該做到以下幾點:
(sender as BackgroundWorker).ReportProgress
方法,傳入事件args這個你已經填充的集合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.