Reputation: 131
We have a 3- tier architecture(UI,BL,DAL) WPF application. I need to handle loading of WPF and DevExpress datagrid with large number of rows. The BL method will return an observable collection of objects which is to be binded to the WPF datagrid. If the number of records are vergy large then the UI become un-responsive. So we need to implement a solution such that show a progress bar with the percentage of the work completed as the BL method executes the query and process the data. Here I need to get the total number of records immediately when the query is executed and after processing the each row I need to show the current index of the item processing in the lable like "processing 1/2000 documents".
What is the best way to achieve the above feature. We are using MVVM pattern. Whether I need to change the way we do the fetching and processing the records in BL (currently the fectch and processing (Map value from datareader to custom object) inside a BL method). Alternatively I am looking for loading the rows in the datagrid in a paged manner as the user scrolls the datagrid.
Any links for samples is appreciated.
Edit: @Big Daddy your solution 1)Add new properties to view model to get the TotalCount and PercentComplete. 2)Pass the viewmodel to the Search method. 3)Use the BGW to update the properties.
The above seems to a workable solution. But I am eager to know whether any other way of solving this without dependednt of the viewmodel. Any design patterns avaialble for this kind of operation?
Upvotes: 1
Views: 3079
Reputation: 45096
So you have all the rows. What processing are you referring to? Rendering? The displayed status of rendering would always be 100% as it does not render until it is done rendering.
It takes the UI a long time to render 2000 rows. There is a lot of formatting and sizing going on.
Break up the UI to display like 40 rows per pages with next and previous page buttons.
If DevExpress datagrid does not support virtualization then look for a grid that does. For speed I like ListView GridView.
Wow a check. You are listening. I give you more.
So get the whole list of IDs at once if that is fast (and you can get a total count). Then just create the 40 objects on demand. If you want to get fancy create the next 40 on a BackGroundWorker. Disable the Next button when you start the BackGroundWorker and enable it in the Complete.
Upvotes: 1
Reputation: 5224
You can use a BackgroundWorker to handle this. It will not block the UI while getting your data and will keep the UI responsive for the user. The BackgroundWorker has a ProgressChanged event that works very well with ProgressBars.
In the projects I've worked on, I've implemented BWs in a client-service/repository. Your view-model can make the calls into this class(es). The methods here will instantiate the BWs, do the work, report progress, and return the data. You'll need to report the progess on the UI, so set-up a property in your view-model and bind your ProgressBar's value to it, like this:
View-Model
private int _percentCompleted;
[DefaultValue(0)]
public int PercentCompleted
{
get { return _percentCompleted; }
set
{
_percentCompleted = value;
RaisePropertyChanged(() => this.PercentCompleted);
}
}
View
<ProgressBar x:Name="SourceBatchUploadProgressBar"
Style="{StaticResource GreenProgressBar}" Grid.Column="1" Grid.Row="1"
Value="{Binding PercentCompleted, UpdateSourceTrigger=PropertyChanged}"
Height="25" Width="200" Margin="5,0,10,5"/>
You'll need to have the BW's ReportProgress event update the PercentCompleted property for this to work. Something like this:
BackgroundWorker.RunWorkerCompleted += (o, e) =>
{
...Update progress
};
If you'd like more details, let me know.
Upvotes: 2