I have a DatGrid, which is bound to var Result_Full = new ObservableCollection<IP_DataRow>(). This is a simple class containing several string & double variables. Nothing difficult.
What I do, is that I read an Excel File (with Telerik RadSpreadProcessing), which parses rows into my class. I do this on a thread so that the UI is not blocked. I have encountered a few problems though:
1) I cannot use ref keyword in a long process which reads excel file (because Result_Full is a public property bound to a DataGrid), but I have to create temporary ObservableCollection<IP_DataRow>(), where the values are placed. Once the process has finished I run the following script for copying the values:
        foreach (var item in tmpFull)
        {
            InvokeOnUIThread(() =>
            {
                Result_Full.Add(item);
            });
        }
What I would like to do, is to be able to see in a real time (if possible) how items are being added to the collection in my DataGrid.
As I am using .Net 4.5 I tried to implement BindingOperations.EnableCollectionSynchronization as was suggested by some other post, yet I could not figure out how to bind my UI bould collection Result_Full to temporary used in a process.
2) Even with the current setup, when (under my UI) I move to my Tab which contains DataGrid (my DataGrid is on a different TabPage), and I try to add new item to the collection with the above mentioned code, it returns an error saying: The calling thread cannot access this object because a different thread owns it., which is rather weird, as InvokeOnUIThread is nothing else but Dispatcher.Invoke(), which should be thread safe?
Any help would be highly appreciated.
EDIT: Showing more code:
This is the process I call from 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;
    }
Here you can see, that I have to create temporary collection tmpError, tmpFull where I gather my data. At the end of process, I manually copy values into my main collections bound to DataGrid. I would like to change this, meaning that values are copied to the main collection (not temporary ones) during the process, so that user can see in a real time how values are added to the collection.
P.S.2:
for uknown reason to me, one of the problems lied in my InvokeOnUIThread call. Once I changed from App.Current.Dispatcher.Invoke(action); to App.Current.Dispatcher.BeginInvoke(action); error with ..different thread owns it stopped.
Application.Current.Dispatcher insteadIn short, I believe you should do the following:
(sender as BackgroundWorker).ReportProgress method, passing in event args this collection you have populated.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With