簡體   English   中英

從后台Worker更新ObservableCollection

[英]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線程擁有它停止。

  1. 您可以使用BackgroundWorker而不是線程來報告進度。 是一個簡單的教程
  2. 我相信簡單地調用Dispatcher將使用上下文的線程,在您的情況下不是UI線程。 請嘗試使用Application.Current.Dispatcher

簡而言之,我相信你應該做到以下幾點:

  1. 在UI線程中創建公共ObservableCollection並將其綁定到DataGrid
  2. 創建后台工作者。 將報告設置為true。 訂閱ReportProgress和DoWork事件。
  3. 運行worker async
  4. 在DoWork處理程序中創建一個列表並讀取一些值。 當你達到一定數量時,讓我們說一百,調用(sender as BackgroundWorker).ReportProgress方法,傳入事件args這個你已經填充的集合。
  5. 在報告進度處理程序中,從您通過事件args傳遞的列表中填充ObservableCollection。
  6. 重復步驟4 - 5直到完成所有操作

暫無
暫無

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

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