I am currently working on a Silverlight 4.0 Application that displays about 13.000 rows in da DataGrid control. A single item contains about 40 String properties and one integer one.
On the page that contains that Grid is a panel where the user can set different weightings. After clicking on an “Update” button Silverlight should do some calculations depending on that settings.
During the calculation reflection is heavily used (and necessary) to get the values of the String properties. Finally as a result a score is calculated and written to the integer field. This needs to be done for every single of the 13.000 objects.
Currently, as a temporary solution, I use a BackgroundWorker instance and the Grids Dispatcher (to get into the UI thread and to be allowed to access the ItemsSource property of the Grid), iterate over each item and calculate the score.
This process needs about 3 minutes and is way too long as the user doesn’t want to wait more than a few seconds. Unfortunately PLinq & Co are not included in Silverlight 4, and even my try to implement a multi-threaded solution for this failed because I need to fall back to the UI Thread (->Dispatcher) to update each element (that implements INotifyPropertyChanged which is forwarded to the Grid) and to access the ItemsSource. So even when using a semi-parallel solution it isn’t really fast because of the dependence on the UI Thread.
Additional to just displaying the data the user needs to be able to filter the data which is not supported by default. Therefore I created a class similar to this one that implements the ICollectionView interface.
Do you have any idea or suggestion what I could try?
Thanks in advance!
My suggestion is don’t use
INotifyPropertyChangedon the objects in question or use anObservableCollection<T>. Instead use a simple class to represent a row and plain oldList<T>to hold the set. Use aCollectionViewSourceobject as theDataGrid.ItemsSourceand let that handle sorting.When recalculating try this first. Switch to a background thread. Create a new
List<T>initialising its capacity to the same as the currently populatedList<T>count. Enumerate the currentList<T>to perform recalculations and then add into the newList<T>. When all are processed switch to the UI thread and simply assign the newList<T>to theCollectionViewSource.Sourceproperty.I suspect that this change will make things plenty quick enough without any need to write any parrallel processing of the list. However it should be too hard to include some parrallel processing if you feel that would help. The big advantage of this approach is that the UI is updated only when all is done.