Creating a Personalized Waiting Window in .NET 6, 7, 8 WPF

Customized Waiting Windows in .NET WPF

A custom loader in a WPF (Windows Presentation Foundation) .Net 6,7,8 application serves the purpose of indicating to the user that the application is performing a task or operation that may take some time to complete.

The customization of loader appearance and theme in the application can be accomplished through the utilization of the NuGet package "DotNet7.Wpf.CustomLoader". As the proprietor of this package, I have incorporated numerous features to facilitate users in tailoring the loader to suit their application's theme.

Loading data from a database

Loading data from a database, processing large amounts of information, or fetching data from a remote server are some of the tasks that could be included. The use of a custom loader improves the user experience by providing visual feedback that the application is actively working on the requested task. This way, users are reassured that progress is being made instead of being left wondering if the application has frozen or if their action has been registered. Users also have the option to create their own personalized loader with a logo.

Moreover, the NuGet library mentioned offers a wide range of custom loaders, with over 30 types available to cater to diverse user requirements. The custom loader comes with a variety of features that allow users to customize their loading experience according to their preferences.

  1. LoaderOverlayColor: Set the color of the overlay displayed behind the loader.
  2. ExpectedLoaderHeight: Define the desired height of the loader.
  3. ExpectedLoaderWidth: Specify the preferred width of the loader.
  4. LoaderFontSize: Adjust the font size of the loader text.
  5. LoaderColor: Choose the color of the loader animation or icon.
  6. LoaderText: Input text to display alongside the loader animation.
  7. LoaderTextColor: Customize the color of the loader text.
  8. LoaderHeaderIcon: Add an icon to the loader header for further customization.
  9. CompanyBranding: Incorporate company branding elements into the loader for a personalized touch.

These features collectively provide users with the flexibility to create a loading experience that aligns seamlessly with their brand identity and user interface preferences.

Implement a custom loader in the application

The steps required to implement a custom loader in the application are as follows.

Step 1. Install the NuGet package of " DotNet7.Wpf.CustomLoader "

DotNet7.Wpf.CustomLoader

Step 2. The incorporation of the loader within the WPF interface.

<Window x:Class="Dotnet7WpfLoaderExample.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:local="clr-namespace:Dotnet7WpfLoaderExample"
        xmlns:WaitWindow="clr-namespace:DotNet7.Wpf.CustomLoader;assembly=DotNet7.Wpf.CustomLoader"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <WaitWindow:AdornedControl x:Name="LoadingAdorner">
        <!-- Keep AdornedControl name as it is "LoadingAdorner" -->
        <!-- Overlay for WaitLoader -->
        <WaitWindow:AdornedControl.AdornerContent>
            <!-- The "WPF.CustomControls.LoadEase" package includes the following loaders, each of which is accompanied by examples provided below. -->
            <!-- You can configure various mentioned properties based on your specific requirements. -->
            <!-- 1. AuroraWaveLoader -->
            <!--<WaitWindow:AuroraWaveLoader LoaderOverColor="Black" ExpectedLoaderHeight="220" LoaderFontSize="15" ExpectedLoaderWidth="220" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 2. BouncingBallLoader -->
            <!--<WaitWindow:BouncingBallLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 3. BouncingBarLoader -->
            <!--<WaitWindow:BouncingBarLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 4. CircleLoader -->
            <!--<WaitWindow:CircleLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 5. ColorFlowConveyorLoader -->
            <!--<WaitWindow:ColorFlowConveyorLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 6. CustomFlowSpinnerLoader -->
            <!--<WaitWindow:CustomFlowSpinner LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 7. CompanyLogoSpinner (User can set company logo in this loader) -->
            <!--<WaitWindow:CompanyLogoSpinner LoaderOverColor="Transparent" ImageNameWithAssemblyPath="pack://application:,,,/Dotnet7WpfLoaderExample;component/Resource/Images/Logo.png" ExpectedLoaderHeight="280" LoaderFontSize="15" ExpectedLoaderWidth="280" LoaderText="Loading.." LoaderTextColor="Red" LoaderBaseColor="Black" LoaderForegroundColor="OrangeRed" LoaderStrokeThickness="8" />-->
            <!-- 8. CustomFlowSpinner -->
            <!--<WaitWindow:CustomFlowSpinner LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 9. DataDashLoader -->
            <!--<WaitWindow:DataDashLoader LoaderOverColor="Black" ExpectedLoaderHeight="280" LoaderFontSize="15" ExpectedLoaderWidth="280" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 10. DottedLoader -->
            <!--<WaitWindow:DottedLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 11. DynamicPulseLoader -->
            <!--<WaitWindow:DynamicPulseLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 12. ElegantSwooshLoader -->
            <!--<WaitWindow:ElegantSwooshLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 13. FlashFleetLoader -->
            <!--<WaitWindow:FlashFleetLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 14. GemstoneGlide -->
            <!--<WaitWindow:GemstoneGlide LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 15. HyperHasteLoader -->
            <!--<WaitWindow:HyperHasteLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 16. InfinityWaveLoader -->
            <!--<WaitWindow:InfinityWaveLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 17. InfinityWaveSpinner -->
            <!--<WaitWindow:InfinityWaveSpinner LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 18. LuminaLoader -->
            <!--<WaitWindow:LuminaLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 19. NovaNestLoader -->
            <!--<WaitWindow:NovaNestLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 20. OpalOrbitLoader -->
            <!--<WaitWindow:OpalOrbitLoader LoaderOverColor="Black" LoaderBackgroundColor="Yellow" LoaderColor="OrangeRed" ExpectedLoaderHeight="30" ExpectedLoaderWidth="650" LoaderFontSize="16" LoaderText="Loading..." LoaderTextColor="White" />-->
            <!-- 21. PolyPulseSpinner -->
            <WaitWindow:PolyPulseSpinner LoaderOverColor="Black" LoaderColor="Blue" ExpectedLoaderHeight="150" ExpectedLoaderWidth="150" LoaderFontSize="10" LoaderText="Loading.." LoaderTextColor="Red" />
            <!-- 22. PrecisionPulseLoader -->
            <!--<WaitWindow:PrecisionPulseLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 23. PrismSpinnerLoader -->
            <!--<WaitWindow:PrismSpinnerLoader LoaderOverColor="Black" ExpectedLoaderHeight="280" LoaderFontSize="15" ExpectedLoaderWidth="280" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 24. QuantumQuikLoader -->
            <!--<WaitWindow:QuantumQuikLoader LoaderOverColor="Black" ExpectedLoaderHeight="100" LoaderFontSize="15" ExpectedLoaderWidth="100" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 25. RingLoader -->
            <!--<WaitWindow:RingLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 26. SonicSyncLoader -->
            <!--<WaitWindow:SonicSyncLoader LoaderOverColor="Transparent" ExpectedLoaderHeight="200" LoaderFontSize="25" ExpectedLoaderWidth="200" LoaderText="Loading" LoaderTextColor="Black" />-->
            <!-- 27. SpinLoader -->
            <!--<WaitWindow:SpinLoader LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 28. StreamlineSpinner -->
            <!--<WaitWindow:StreamlineSpinner LoaderOverColor="Transparent" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 29. SwirlLoader -->
            <!--<WaitWindow:SwirlLoader LoaderOverColor="Black" ExpectedLoaderHeight="280" LoaderFontSize="15" ExpectedLoaderWidth="280" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 30. TurboTransitLoader -->
            <!--<WaitWindow:TurboTransitLoader LoaderOverColor="Black" ExpectedLoaderHeight="280" LoaderFontSize="15" ExpectedLoaderWidth="280" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 31. VectorVeloLoader -->
            <!--<WaitWindow:VectorVeloLoader LoaderOverColor="Black" ExpectedLoaderHeight="150" LoaderFontSize="12" ExpectedLoaderWidth="150" LoaderText="Loading" LoaderTextColor="Red" />-->
            <!-- 32. VividVortexSpinner -->
            <!--<WaitWindow:VividVortexSpinner LoaderOverColor="Black" ExpectedLoaderHeight="150" LoaderFontSize="12" ExpectedLoaderWidth="150" LoaderText="Loading" LoaderTextColor="Red" />-->
            <!-- 33. WPFLoadEase -->
            <!--<WaitWindow:WPFLoadEase LoaderOverColor="Black" ExpectedLoaderHeight="180" LoaderFontSize="15" ExpectedLoaderWidth="180" LoaderText="Loading.." LoaderTextColor="Red" />-->
            <!-- 34. MicrosoftLoader -->
            <!--<WaitWindow:MicrosoftLoader LoaderHeaderIcon="pack://application:,,,/Dotnet7WpfLoaderExample;component/Resource/Images/LoaderHeaderIcon.jpg" LoaderOverColor="Black" LoaderFontSize="10" LoaderBodyColor="Black" LoaderHeaderFontSize="20" LoaderBackgroundColor="Gray" LoaderColor="OrangeRed" LoaderHeaderText="Wait Window" LoaderHeaderTextColor="White" LoaderHeaderTheme="Blue" LoaderText="If you're looking to create a loader similar to those found in Microsoft Visual Studio using WPF and C#, you can create a custom loader control with a design inspired by Visual Studio's loading animations. Here's a simplified example of how you can create such a loader" LoaderTextColor="White" />-->
            <!-- 35. GalacticWPFSpinner -->
            <!--<WaitWindow:GalacticWPFSpinner ExpectedLoaderHeight="180" LoaderColor="YellowGreen" LoaderOverColor="Transparent" LoaderFontSize="10" ExpectedLoaderWidth="180" LoaderText="Searching" LoaderTextColor="Black" />-->
        </WaitWindow:AdornedControl.AdornerContent>
        <Grid>
            <!-- Main Content of the application -->
            <TextBlock Text="Demo"/>
            <Button Content="Test Loader" Height="40" Width="200" Margin="120,177,480,217" Command="{Binding ShowLoaderWithoutInstance}"/>
        </Grid>
    </WaitWindow:AdornedControl>
</Window>

Note. Users can choose to use any of the loaders mentioned earlier. Extra loaders have been disabled to avoid confusion. Users are restricted to utilizing just one loader at a time.

Step 3. Invoke the custom loader without requiring its instantiation.

// Stop Loader function
LoaderHandler.HideLoader();

// Start Loader function
LoaderHandler.ShowLoader();

Step 4. Utilize the custom loader within the MVVM design pattern by implementing dependency injection.

using DotNet7.Wpf.CustomLoader.Utility;
using DotNet7.Wpf.CustomLoader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;

namespace Dotnet7WpfLoaderExample
{
    public class MainWindowViewModel
    {
        ICustomLoaderService? customLoaderService = null;
        DispatcherTimer? timer = null;
        public ICommand ShowLoaderWithoutInstance { get; }
        
        public MainWindowViewModel(ICustomLoaderService customLoaderService)
        {
            this.customLoaderService = customLoaderService;
            ShowLoaderWithoutInstance = new RelayCommand(()=>ShowLoader());
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(10); // Adjust the interval as needed
            timer.Tick += Timer_Tick;
            timer.Start();
            //Start the loader by utilizing the service handler for dependency injection.
            customLoaderService.ShowLoader();
            //To start the loader without the need for creating an instance.
            //LoaderHandler.ShowLoader();
        }
        
        private void ShowLoader()
        {
            LoaderHandler.ShowLoader();
        }
        
        private void Timer_Tick(object sender, EventArgs e)
        {
            //To stop the loader by utilizing the service handler for dependency injection.
            customLoaderService.HideLoader();
            //To stop the loader without the need for creating an instance.
            //LoaderHandler.HideLoader();
        }
    }
}

Step 5. App.xaml.cs

using DotNet7.Wpf.CustomLoader;
using Microsoft.Extensions.DependencyInjection;
using System.Windows;

namespace Dotnet7WpfLoaderExample
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public static ServiceProvider? serviceProvider = null;
        
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            // Create a service collection
            var services = new ServiceCollection();
            
            // Register your services
            services.AddSingleton<ICustomLoaderService, CustomLoaderService>();
            services.AddTransient<MainWindowViewModel>();
            serviceProvider = services.BuildServiceProvider();
        }
    }
}

Step 6. Outlooks of some customized loader.

  • SonicSyncLoader
    SonicSyncLoader
  • VectorVeloLoader
    VectorVeloLoader
  • OpalOrbitLoader
    OpalOrbitLoader
  • PolyPulseSpinner
    PolyPulseSpinner

Repository Path: https://github.com/OmatrixTech/Dotnet7WpfLoaderExample