When you're designing your application, you need to consider how to handle data loading in order to ensure the application always remains responsive to the user. Generally this is done by loading data asynchronously on a background thread, while the user may continue to interact with the application.
The issue is that without proper visualization, the user may wonder whether anything is happening. This leads to the use of a progress bar to indicate that some activity is being executed in the background.
Once the data has been loaded the progress bar should be hidden and the relevant controls to display the data should be shown.
Let's walk through with a few examples working with progress bars in WinForms and WPF.
The first step is to asynchronously load your data so that the application UI remains responsive during longer-than-usual load times. This is handled pretty easily in .NET using an awaited method call. It means that any code that happens after the await, will not run until the operation is complete. It’s the easiest solution as shown below.
private async Task LoadData()
{
// show progress bar
progressBar1.Visible = true;
await LoadDataAsync();
// hide progress bar
progressBar1.Visible = false;
}
All you have to do is set the progress bar visibility before you await the loading of data, and then set it invisible when the operation is complete. This works well if the progress bar is “indeterminate”, which means it will keep looping through the loading animation indefinitely until you stop it.
It’s a common design paradigm today to display an indeterminate progress bar, or ring, as data is loading. This is popular because with unpredictable networks we don’t know exactly how long it may take. The server we are calling may not be capable or willing to inform us how long it will take either.
To create an indeterminate progress bar in WinForms, set its Style property to Marquee. In WPF, set its IsIndeterminate property to True.
The downside to indeterminate progress bars is that the user doesn’t know how much time is remaining. The alternative is to report progress to the progress bar as your data is loaded. This approach is popular for installing software so that the user knows exactly how much progress (and sometimes how much time as well) is remaining. This may be possible to use during data load as well depending on your data solution.
Let’s take a look at a code example that uses a background worker, rather than awaited code so that we have complete control over updating the progress bar.
BackgroundWorker worker = new BackgroundWorker();
public App()
{
InitializeComponent();
// set background worker
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.WorkerReportsProgress = true;
}
To set up the background worker, we must listen to the ProgressChanged, RunWorkerCompleted, and DoWork events.
Here’s what we do in each:
To kick this whole process off, just call the RunWorkerAsync method.
// run background worker
worker.RunWorkerAsync();
To see a full example, check out the “Performance” FlexGrid demo in our WinForms Control Explorer.
ComponentOne provides custom progressbar controls for WPF. The C1ProgressBar control is modeled after the native progress indicators used on Windows 8-10 to provide a modern user experience. It can display as an animated looping pattern of dots to indicate that an indeterminate operation is in progress. Also, the C1ProgressIndicator control shows a loading ring.
You can download the C1ProgressBar and C1ProgressIndicator controls as part of the C1.WPF core library.