Windows Phone: Progress Indicator Plus

In Windows Phone, progress indicator on System Tray is a quick and easy way to indicate that some activity is running in the background. It is all right if you want to indicate progress from a single thread. What if you have multiple threads running and all need to use progress indicator?

I created a ProgressBarManager wrapper class to handle multiple thread progress indication scenario. This class can work in both scenarios – indeterminate or determinate, but in case of multiple background processes the preferable way is indeterminate. The accompanied progress text from different processes can show progress value in the text. Following is example screen shot of ProgressBarManager in action.
MultipleMessage

Usage Example

At class level define ProgressBarManager:

        ProgressBarManager ProgressBarManager = new ProgressBarManager();

In constructor of the form where you wish to show progress bar with multiple clients, instantiate the class like so:

        SystemTray.SetProgressIndicator(this, new ProgressIndicator());
        ProgressBarManager.Hook(SystemTray.ProgressIndicator);

Update ProgressBar from different processes with the ProgressBarManager.Show(). In this example I have a button which starts two background threads which update progress bar asynchronously. The button’s click method is as follows:

       private void button1_Click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker _bw = new BackgroundWorker();
            _bw.DoWork += new DoWorkEventHandler(
                (object caller, DoWorkEventArgs workArgs) =>
                {
                    for (int i = 0; i <= 10; i++)
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            double _val = (double)i / 10d;
                            double _percent = _val * 100d;
                            ProgressBarManager.Show(1, string.Format("2: Progress-{0}%", _percent), false, _val);
                        });
                        Thread.CurrentThread.Join(230);
                    }
                    ProgressBarManager.Hide(1);
                }
                );

            BackgroundWorker _bw2 = new BackgroundWorker();
            _bw2.DoWork += new DoWorkEventHandler(
                (object caller, DoWorkEventArgs workArgs) =>
                {
                    for (int i = 0; i <= 10; i++)
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            double _val = (double)i / 10d;
                            double _percent = _val * 100d;
                            ProgressBarManager.Show(2, string.Format("2: Progress-{0}%", _percent), false, _val);
                        });
                        Thread.CurrentThread.Join(500);
                    }
                    ProgressBarManager.Hide(2);
                }
                );
            _bw.RunWorkerAsync();
            _bw2.RunWorkerAsync();
        }

ProgressBarManager Class

Following is full code of ProgressBarManager class:

using System;
using System.ComponentModel;
using System.Collections.Generic;
using Microsoft.Phone.Shell;
using System.Windows.Data;
using System.Windows;
namespace YourCompany.UI.Controls
{
    public class ProgressBarManager : INotifyPropertyChanged
    {
        private Dictionary<int, string> _clients = new Dictionary<int, string>();
        private bool _show;
        private bool _inDeterminant;
        private string _text;
        private double _value;
        public bool ShowProgress { get { return _show; } }
        public bool ProgressInDeterminant { get { return _inDeterminant; } }
        public string ProgressText { get { return _text; } }
        public Double Value { get { return _value; } }

        public event PropertyChangedEventHandler PropertyChanged;

        public void Show(int ClientID, string Text, bool IsDeterminant, double Value)
        {
            if (!_clients.ContainsKey(ClientID))
            {
                _clients.Add(ClientID, Text);
            }
            else
            {
                _clients[ClientID] = Text;
            }
            _value = Value;
            _inDeterminant = !IsDeterminant;
            updateProperties();
        }
        public void Show(int ClientID, string Text)
        {
            if (!_clients.ContainsKey(ClientID))
            {
                _clients.Add(ClientID, Text);
            }
            else
            {
                _clients[ClientID] = Text;
            }
            updateProperties();
        }
        public void Hide(int ClientId)
        {
            if (_clients.ContainsKey(ClientId))
            {
                _clients.Remove(ClientId);
            }
            updateProperties();
        }
        public void Hook(ProgressIndicator FormProgressIndicator)
        {
            #region setup ProgressIndicator
            Binding _binding;
            _binding = new Binding("ShowProgress");
            _binding.Source = this;
            _binding.Mode = BindingMode.TwoWay;
            BindingOperations.SetBinding(FormProgressIndicator, ProgressIndicator.IsVisibleProperty, _binding);
            _binding = new Binding("ProgressInDeterminant");
            _binding.Source = this;
            _binding.Mode = BindingMode.TwoWay;
            BindingOperations.SetBinding(FormProgressIndicator, ProgressIndicator.IsIndeterminateProperty, _binding);
            _binding = new Binding("ProgressText");
            _binding.Source = this;
            _binding.Mode = BindingMode.TwoWay;
            BindingOperations.SetBinding(FormProgressIndicator, ProgressIndicator.TextProperty, _binding);
            _binding = new Binding("Value");
            _binding.Source = this;
            _binding.Mode = BindingMode.TwoWay;
            BindingOperations.SetBinding(FormProgressIndicator, ProgressIndicator.ValueProperty, _binding);
            #endregion
        }
        private void updateProperties()
        {
            if (_clients.Count == 0)
            {
                _show = false;
                _text = "";
            }
            else
            {
                _show = true;
                string _m_seperator = "";
                _text = "";
                foreach (KeyValuePair<int, string> _keyvaluePair in _clients)
                {
                    _text = _text + _m_seperator + _keyvaluePair.Value;
                    _m_seperator = ", ";
                }
            }
            onPropertyChanged("ShowProgress");
            onPropertyChanged("ProgressInDeterminant");
            onPropertyChanged("ProgressText");
            onPropertyChanged("Value");
        }
        private void onPropertyChanged(string PropertyName)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
                }
            });
        }
    }
}
Advertisements

3 thoughts on “Windows Phone: Progress Indicator Plus

  1. Pingback: Progress Indicator Plus

  2. Pingback: Windows Phone: Progress Indicator Plus

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s