Click here to Skip to main content
15,895,011 members
Articles / Mobile Apps / Windows Phone 7

Implementing Wizard Functionality for Windows Phone 7 Applications

Rate me:
Please Sign up or sign in to vote.
4.88/5 (12 votes)
5 Aug 2011CPOL23 min read 38.7K   683   17  
This article presents how to build a wizard for WP7 applications.
using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WizardLibrary
{
    public class Wizard:INotifyPropertyChanged
    {
        #region fields
        private string title;
        private ObservableCollection<WizardStep> steps;
        private WizardStep currentStep;
        private bool showCancel;
        #endregion

        public Wizard()
        {
            steps = new ObservableCollection<WizardStep>();
            steps.CollectionChanged += (o, e) => {
                OnStepCollectionChanged();
            };
        }

        #region inpc implementation
        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        #endregion

        #region properties
        public string Title
        {
            get { return title; }
            set
            {
                if (title == value)
                    return;
                title = value;
                NotifyPropertyChanged("Title");
            }
        }
        public ObservableCollection<WizardStep> Steps
        {
            get { return steps; }
        }
        public WizardStep CurrentStep
        {
            get { return currentStep; }
            set
            {
                if (currentStep == value)
                    return;
                currentStep = value;
                NotifyPropertyChanged("CurrentStep");
                Invalidate();
            }
        }
        public bool ShowCancel
        {
            get { return showCancel; }
            set
            {
                if (showCancel == value)
                    return;
                showCancel = value;
                NotifyPropertyChanged("ShowCancel");
            }
        }
        #endregion

        #region validation properties
        public bool CanNext
        {
            get
            {
                //can always move forward if valid
                int idx = steps.IndexOf(currentStep);
                return idx < (steps.Count - 1) && CurrentStep.IsValid();
            }
        }
        public bool CanPrevious
        {
            get
            {
                WizardStep prev = GetPreviousAvailableStep();
                return prev != null;
            }
        }
        public bool CanFinish
        {
            get
            {
                //can only finish if the user is on the last step
                //derived classes can say otherwise
                int idx = steps.IndexOf(currentStep);
                if (steps.Count == 0 || currentStep == null || !currentStep.IsValid())
                    return false;
                if (idx < steps.Count - 1 && currentStep.AllowFinish)
                    return true;
                return idx == steps.Count - 1;
            }
        }
        public bool CanCancel
        {
            get
            {
                //can cancel only if show cancel is true and there are steps
                return steps.Count > 0 && ShowCancel;
            }
        }
        #endregion

        #region events
        public event EventHandler WizardCanceled;
        public event EventHandler WizardFinished;
        #endregion

        #region helper functions
        protected void OnWizardCanceled()
        {
            if (WizardCanceled != null)
                WizardCanceled(this, EventArgs.Empty);
        }
        protected void OnWizardFinished()
        {
            if (WizardFinished != null)
                WizardFinished(this, EventArgs.Empty);
        }
        private WizardStep GetPreviousAvailableStep()
        {
            int idx = steps.IndexOf(currentStep);
            for (int i = idx - 1; i >= 0; i--)
            {
                if (steps.ElementAt(i).AllowReturn)
                    return steps.ElementAt(i);
            }
            return null;
        }
        private void OnStepCollectionChanged()
        {
            //set the current step only when the first step is added or when
            //the current step is removed from the wizard
            if (steps.Count == 1 || steps.IndexOf(currentStep) == -1)
                CurrentStep = steps.ElementAt(0);
        }
        #endregion

        #region virtual methods 
        public virtual void Next()
        {
            if (CanNext)
            {
                //move to the next step
                int idx = steps.IndexOf(currentStep);
                CurrentStep = steps.ElementAt(idx + 1);
            }
        }
        
        public virtual void Previous()
        {
            //take into account the allowReturn value
            WizardStep prev = GetPreviousAvailableStep();
            if (prev != null)
            {
                CurrentStep = prev;
            }
        }
        
        public virtual void Finish()
        {
            if (CanFinish)
                OnWizardFinished();
        }
        
        public virtual void Cancel()
        {
            if (CanCancel)
                OnWizardCanceled();
        }
        
        #endregion

        #region public methods
        public void AddStep(WizardStep step)
        {
            if (step.Wizard != null && step.Wizard != this)
                step.Wizard.Steps.Remove(step);
            if (step.Wizard == this)
                return;
            step.Wizard = this;
            Steps.Add(step);
        }
        public void AddStep(string title, object content)
        {
            AddStep(title, content, false, true);
        }
        public void AddStep(string title, object content, bool allowFinish, bool allowReturn)
        {
            WizardStep vm = new WizardStep();
            vm.Title = title;
            vm.Content = content;
            vm.Wizard = this;
            vm.AllowFinish = allowFinish;
            vm.AllowReturn = allowReturn;
            Steps.Add(vm);
        }
        public virtual void Invalidate() 
        {
            NotifyPropertyChanged("CanNext");
            NotifyPropertyChanged("CanPrevious");
            NotifyPropertyChanged("CanCancel");
            NotifyPropertyChanged("CanFinish");
        } 
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions