Saturday, July 13, 2013

WPF busy indicator implementation with Singleton Pattern

What is Singleton pattern ?

Singleton pattern ensure that a class has only one instance and provide a global point of access to that instance. Normally singleton object store data which is common to for all over the application.

Using this pattern now we are going to implement a busy indicator which is going to be a common for your whole WPF application.

Before start the development we need to download  Extended WPF Toolkit and latest Microsoft Prism library and extract those folders to your hard drive. Download links are  :
      Download PRISM

1. Create new WPF project named  by BusyIndicatorExample.

2. Right click on project reference and add the desktop version of  "Microsoft.Practices.Prism.dll" from extracted prism libraries.

3. Now we will implement the singleton class which going to be a data context for our WPF BusyIndictor controller. To do that right click on project  and create new class called BusyIndicatorManager. Implement the class as bellow.

using Microsoft.Practices.Prism.ViewModel;
using System.Collections.Generic;
using System.Linq;

namespace BusyIndicatorExample
{
    public class BusyIndicatorManager : NotificationObject
    {
        #region Membervariables

        private Dictionary<int, string> busyParameters;

        #endregion

        #region Constructor

        private BusyIndicatorManager()
        {
            isBusy = false;
            message = string.Empty;
            busyParameters = new Dictionary<int, string>();
        }

        #endregion

        #region Singleton Implementation

        private static BusyIndicatorManager instance;
        private static object syncRoot = new object();

        public static BusyIndicatorManager Instance
        {
            get
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new BusyIndicatorManager();
                    }
                    return instance;
                }
            }
        }

        #endregion

        #region Public Properties

        private bool isBusy;
        public bool IsBusy
        {
            get { return isBusy; }
            private set
            {
                isBusy = value;
                RaisePropertyChanged("IsBusy");
            }
        }

        private string message;
        public string Message
        {
            get { return message; }
            private set
            {
                message = value;
                RaisePropertyChanged("Message");
            }
        }

        #endregion

        #region Public Methods

        public void ShowBusy(int id, string busyMessage)
        {
            if (!busyParameters.ContainsKey(id))
            {
                busyParameters.Add(id, busyMessage);
                IsBusy = true;
                Message = busyMessage;
            }
            else
            {
                busyParameters[id] = busyMessage;
                IsBusy = true;
                Message = busyMessage;
            }
        }

        public void CloseBusy(int id)
        {
            if (busyParameters.ContainsKey(id))
                busyParameters.Remove(id);

            if (busyParameters.Count == 0)
            {
                IsBusy = false;
                Message = string.Empty;
            }
            else
            {
                IsBusy = true;
                Message = busyParameters.Last().Value;
            }
        }

        #endregion
    }
}

Above this singleton implementation you can see that there are two public properties called IsBusy and Message , So they are the going to be bind with WPF busy indicator control. Also you can call ShowBusy and CloseBusy methods from anywhere in you application using singleton instance.

4. Now we will implement the our view for busy indicator. First add "Xceed.Wpf.Toolkit.dll" file as a reference from extracted Extended WPF Toolkit folder.


5. Now we will implement our MainPage.xaml view as bellow.

<Window x:Class="BusyIndicatorExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="40"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Name="btnRunBusy" Height="30" Width="150" Content="Run BusyIndicator" Click="btnRunBusy_Click" Margin="0,0,10,0"/>
            <Button Name="btnCloseBusy" Height="30" Width="150" Content="Close BusyIndicator" Click="btnCloseBusy_Click"/>
        </StackPanel>
        
        <xctk:BusyIndicator Grid.Row="1" Name="busyIndicator" IsBusy="{Binding IsBusy}" BusyContent="{Binding Message}">
            <Grid>
                

            </Grid>
        </xctk:BusyIndicator>
    </Grid>
</Window>

6. Now go to MainWindow.xaml.cs and modify the class implementation as bellow.

In class constructor we assign busy indicator DataContext as singleton instance of BusyIndicatorManager. 

7. Now Run the application and click on Run BusyIndicator button and then busy indicator will visible in our application.


Here we call the ShowBusy method which is implemented in BusyIndicatorManager class, using it's singleton instance. Inside the method we will set IsBusy property into true and Message property with message which are  bind to the BusyIndicator controller in our MainPage.xaml.

8. Now click on the "Close BusyIndicator" button and then running  busy indicator will disappear from the application. Because here we call the CloseBusy method which is implemented in BusyIndicatorManager class using it's singleton instance and Inside the method we set IsBusy property into "False".


Happy Coding!!!!!!!!!!!!!!!!!!!