Often we need to perform some time-consuming tasks in our code. A good app should use a loading animation or progress bar while performing a long task, and if we don’t use any loading sign or indicator to the user while performing a long job, it will annoy the user as the user may think that the app is in hang-state, which will surely break the user experience.
Windows Presentation Foundation provides us with a “ProgressBar” control, which is used to show a progress bar to user while performing a task. We will use this control to show the user a percentage bar. First, we will display a progress bar, then we will see how to use a gif image to display a loading animation instead of the progress bar. So, let’s get started.
Before starting, you should download .Net Core setup, and .Net Core SDK. I will recommend you to install version 3.0.1XX of .Net Core SDK.
Now, Open visual studio and create a .Net Core WPF App.
Creating Progress bar: After creating WPF .Net Core project, create a progress bar control in the MainWindow.xaml. We also need a TextBlock to display the percentage of the progress, fr this purpose, we will bind the value of progress bar with the TextBlock. The following code will create a progress bar and a Text block, place the code inside the grid element.
<ProgressBar Name="MyProgressBar" HorizontalAlignment="Left" Margin="75,100,0,0" Height="20" VerticalAlignment="Top" Width="150"/> <TextBlock Margin="25,-42,0,0" Name="MyProgressLabel" Text="{Binding ElementName=MyProgressBar, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
The task which we want to perform and the progress bar cannot work at the same time, because they require separate threads to execute, so we need to execute them in parallel by running them in separate threads. In this tutorial, we will use background workers to accomplish this job.
Background workers are very simple to use. To make use of them we need to bind three methods to the instance of Background Worker, One method to perform the task, the second method to change the progress percentage, and the third to run after completing the task. Let’s see how we can code them.
First, declare an object of Background Worker, we will declare it as global because we need it in different methods. Write the following code just above the public partial class MainWindow : Window
BackgroundWorker worker;
The BackgroundWorker requires the System.ComponentModel namespace.
Create a method in MainWindow.xaml.cs with any name, having two parameters of type object and DoWorkEventArgs respectively, we will write our long task here.
private void Worker_DoWork(object sender, DoWorkEventArgs e) { }
Now create another method with any name, having two parameters of type object and ProgressChangedEventArgs respectively, this method will execute when the percentage of the task is changed.
void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { }
Now create another method with any name, having two parameters of type object and RunWorkerCompletedEventArgs respectively, this method will execute after the execution of worker_DoWork method.
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { }
Create a button in the MainWindow.xaml file, our task will execute after pressing this button.
<Button Name="PerformTask" Content="Execute job" Click="PerformTask_Click" Margin="110,50,0,0" Width="80" Height="20" HorizontalAlignment="Left" VerticalAlignment="Top"/>
Now, in the event handler of the button we just created, we will run our task. For this purpose, we first need to bind the three methods we discussed above with the worker object i.e. Worker_DoWork, Worker_ProgressChanged, and Worker_RunWorkerCompleted, then we will execute the worker. The following lines of code will do this. Write them inside PerformTask_Click event handler of Execute job button.
MyProgressBar.Visibility = Visibility.Visible; //Make Progressbar visible MyProgressLabel.Visibility = Visibility.Visible; //Make TextBlock visible PerformTask.IsEnabled = false; //Disabling the button worker = new BackgroundWorker(); //Initializing the worker object worker.ProgressChanged += Worker_ProgressChanged; //Binding Worker_ProgressChanged method worker.DoWork += Worker_DoWork; //Binding Worker_DoWork method worker.WorkerReportsProgress = true; //telling the worker that it supports reporting progress worker.RunWorkerCompleted += Worker_RunWorkerCompleted; //Binding worker_RunWorkerCompleted method worker.RunWorkerAsync(); //Executing the worker
We need to hide the progress bar and the text block and will only display it after pressing the Execute job button. To hide them, we will use Visibility property with the value Collapsed. The following is the updated code for the progress bar and the text block.
<ProgressBar Visibility="Collapsed" Name="MyProgressBar" HorizontalAlignment="Left" Margin="75,100,0,0" Height="20" VerticalAlignment="Top" Width="150"/> <TextBlock Visibility="Collapsed" Margin="25,-42,0,0" Name="MyProgressLabel" Text="{Binding ElementName=MyProgressBar, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
Now, its time to write the code for Worker_DoWork. We need to write some time-consuming task here, for this, we will calculate the sum of the first 100000 numbers. The following code will calculate the sum, place the code inside private void Worker_DoWork(object sender, DoWorkEventArgs e).
long sum = 0; long total = 100000; for (long i = 1; i <= total; i++) { sum += i; int percentage = Convert.ToInt32(((double)i / total) * 100); Dispatcher.Invoke(new System.Action(() => { worker.ReportProgress(percentage); })); } MessageBox.Show("Sum: " + sum);
The worker.ReportProgress(percentage); calls the Worker_ProgressChanged to update the progress percentage. In Worker_ProgressChanged, we just need to change the value property of the progress bar. The following code of line will do this, write this line inside void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e).
MyProgressBar.Value = e.ProgressPercentage;
After the worker completes its job, we just need to hide the progress bar and the associated text block. The following lines of code will do that, place them inside private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
MyProgressBar.Visibility = Visibility.Collapsed; MyProgressLabel.Visibility = Visibility.Collapsed; PerformTask.IsEnabled = true;
Now its time to run our code, the code will produce the output as follows.
Indeterminate Progress bar:
If you want to make progress bar indeterminate, then use IsIndeterminate=”True” in the progress bar. The indeterminate progress bar will look like the following:
Using GIF image as animation:
You can also use a GIF image as a loading indicator in your project. The WPF does not support animating the GIF image as default, if you try to use it just like JPG or PNG image, it will not animate. Fortunately, there is a NuGet package called WpfAnimatedGif which can animate the GIF images. Let’s see how to make use of it.
First of all, install WpfAnimatedGif, for this, go to Tools > Nuget Package Manager > Package Manager Console, then type Install-Package WpfAnimatedGif, then in MainWindow.xaml file, add xmlns:gif=”http://wpfanimatedgif.codeplex.com”as XML namespace. after that, add the GIF image in your project, remove progress bar control and finally, create an image control as follows:
<Image Name="imgCircle" Visibility="Collapsed" Width="100" Height="100" gif:ImageBehavior.AnimatedSource="/circle.gif" />
The complete MainWindow.xaml file will look like this:
<Window x:Class="LoadingAnimation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:gif="http://wpfanimatedgif.codeplex.com" xmlns:local="clr-namespace:LoadingAnimation" mc:Ignorable="d" Title="MainWindow" Height="300" Width="300"> <Grid><Image Name="imgCircle" Visibility="Collapsed" Width="100" Height="100" gif:ImageBehavior.AnimatedSource="/circle.gif" /> <Button Name="PerformTask" Content="Execute job" Click="PerformTask_Click" Margin="110,50,0,0" Width="80" Height="20" HorizontalAlignment="Left" VerticalAlignment="Top"/> </Grid> </Window>
Now run the project, the output of the project will look like this:
You can download the complete project here.
Here’re some more related articles for you:
– A COMPLETE GUIDE TO SECURE YOUR ASP.NET CORE WEB API
– WHAT STATS AND SURVEYS ARE SAYING ABOUT .NET CORE IN 2020
– HOW I BOOSTED MY ASP.NET CORE APP & API PERFORMANCE 250% BY CACHING