Implementing a Progress Bar Popup in WPF Applications

Functionality Overview:

When a long-running task is initiated, a popup window containing a progress bar is displayed to provide real-time feedback to the user. Up on task completion, a notificatino message is shown.

1. Designing the Progress Bar Popup Window

The XAML for the popup window:

<Window x:Class="WpfApp.ProgressPopup"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        WindowStartupLocation="CenterScreen"
        WindowStyle="None" 
        ResizeMode="NoResize"
        AllowsTransparency="True"
        Topmost="True"
        Title="Processing..." Height="100" Width="400">
    <Grid>
        <ProgressBar Margin="10"
                     Name="TaskProgressBar"
                     HorizontalAlignment="Stretch" 
                     Height="30" 
                     VerticalAlignment="Center" 
                     DataContext="{Binding}" 
                     Value="{Binding CurrentProgress}"
                     Foreground="SteelBlue"/>
    </Grid>
</Window>

Code-behind for the progress window:

using System.Windows;

namespace WpfApp
{
    public partial class ProgressPopup : Window
    {
        public ProgressPopup()
        {
            InitializeComponent();
            DataContext = new ProgressModel(this);
        }
    }
}

2. Creating the Progress Data Model

The model implementing INotifyPropertyChanged:

using System.ComponentModel;
using System.Windows;

namespace WpfApp
{
    public class ProgressModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private readonly Window _hostWindow;

        public ProgressModel(Window hostWindow)
        {
            _hostWindow = hostWindow;
        }

        private int _currentProgress;
        public int CurrentProgress
        {
            get => _currentProgress;
            set
            {
                _currentProgress = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentProgress)));

                if (_currentProgress >= 100)
                {
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        _hostWindow.Close();
                    });
                }
            }
        }
    }
}

3. Implementing the Main Application Window

Main window XAML:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Main Application" Height="300" Width="500">
    <Grid>
        <Button x:Name="StartTaskButton" 
                Content="Execute Task" 
                FontSize="16" 
                Click="StartTaskButton_Click" 
                Margin="20" 
                HorizontalAlignment="Center" 
                VerticalAlignment="Center"/>
    </Grid>
</Window>

Main window code-behind:

using System.Threading.Tasks;
using System.Windows;

namespace WpfApp
{
    public partial class MainWindow : Window
    {
        private ProgressPopup _progressWindow;

        public MainWindow()
        {
            InitializeComponent();
        }

        private async void StartTaskButton_Click(object sender, RoutedEventArgs e)
        {
            _progressWindow = new ProgressPopup();
            _progressWindow.Show();

            await Task.Run(() =>
            {
                for (int step = 0; step <= 100; step++)
                {
                    _progressWindow.Dispatcher.Invoke(() =>
                    {
                        _progressWindow.TaskProgressBar.Value = step;
                    });
                    System.Threading.Thread.Sleep(25);
                }
            });

            MessageBox.Show("Task completed successfully!");
        }
    }
}

Tags: WPF progress bar Popup Window mvvm asynchronous

Posted on Wed, 29 Jul 2026 17:07:32 +0000 by joeysarsenal