Click here to Skip to main content
15,896,118 members
Articles / Desktop Programming / WPF

WPF.JoshSmith

Rate me:
Please Sign up or sign in to vote.
4.99/5 (51 votes)
13 Jul 2008CPOL5 min read 391.3K   4.8K   263  
A free library of controls and utility classes for use in WPF applications.
// Copyright (C) Josh Smith - July 2008
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Input;
using System.Windows.Markup;

namespace WPF.JoshSmith.Input
{
    /// <summary>
    /// This is a command that simply aggregates other commands into a group.
    /// This command's CanExecute logic delegates to the CanExecute logic of 
    /// all the child commands.  When executed, it calls the Execute method
    /// on each child command sequentially.
    /// </summary>
    /// <remarks>
    /// Documentation: http://www.codeproject.com/KB/WPF/commandgroup.aspx
    /// </remarks>
    [ContentProperty("Commands")]
    public class CommandGroup : ICommand
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance.
        /// </summary>
        public CommandGroup()
        {
            // Parameterless public ctor required for XAML instantiation.
        }

        #endregion // Constructor

        #region Commands

        private ObservableCollection<ICommand> _commands;

        /// <summary>
        /// Returns the collection of child commands.  They are executed
        /// in the order that they exist in this collection.
        /// </summary>
        public ObservableCollection<ICommand> Commands
        {
            get
            {
                if (_commands == null)
                {
                    _commands = new ObservableCollection<ICommand>();
                    _commands.CollectionChanged += this.OnCommandsCollectionChanged;
                }

                return _commands;
            }
        }

        void OnCommandsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // We have a new child command so our ability to execute may have changed.
            this.OnCanExecuteChanged();

            if (e.NewItems != null && 0 < e.NewItems.Count)
            {
                foreach (ICommand cmd in e.NewItems)
                    cmd.CanExecuteChanged += this.OnChildCommandCanExecuteChanged;
            }

            if (e.OldItems != null && 0 < e.OldItems.Count)
            {
                foreach (ICommand cmd in e.OldItems)
                    cmd.CanExecuteChanged -= this.OnChildCommandCanExecuteChanged;
            }
        }

        void OnChildCommandCanExecuteChanged(object sender, EventArgs e)
        {
            // Bubble up the child commands CanExecuteChanged event so that
            // it will be observed by WPF.
            this.OnCanExecuteChanged();
        }

        #endregion // Commands

        #region ICommand Members

        /// <summary>
        /// Returns true if all of the commands in the group can execute.
        /// </summary>
        public bool CanExecute(object parameter)
        {
            foreach (ICommand cmd in this.Commands)
                if (!cmd.CanExecute(parameter))
                    return false;

            return true;
        }

        /// <summary>
        /// Raised when something changes whether the command can or cannot execute.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        /// <summary>
        /// Subclasses can invoke this method to raise the CanExecuteChanged event.
        /// </summary>
        protected virtual void OnCanExecuteChanged()
        {
            if (this.CanExecuteChanged != null)
                this.CanExecuteChanged(this, EventArgs.Empty);
        }

        /// <summary>
        /// Executes each command in the group sequentially.
        /// </summary>
        public void Execute(object parameter)
        {
            foreach (ICommand cmd in this.Commands)
                cmd.Execute(parameter);
        }

        #endregion // ICommand Members
    }
}

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 (Senior)
United States United States
Josh creates software, for iOS and Windows.

He works at Black Pixel as a Senior Developer.

Read his iOS Programming for .NET Developers[^] book to learn how to write iPhone and iPad apps by leveraging your existing .NET skills.

Use his Master WPF[^] app on your iPhone to sharpen your WPF skills on the go.

Check out his Advanced MVVM[^] book.

Visit his WPF blog[^] or stop by his iOS blog[^].

See his website Josh Smith Digital[^].

Comments and Discussions