A bindable class to publish EventAggregator events

Apr 22, 2010 at 1:21 AM

I don't know if anyone has done this but I have created a simple two simple classes (one a base class that handles ICommand and the other a generic class for taking in different events) that implement ICommand, provide a mechanism for injecting a CanExecute delegate and then publishes an event in an EventAggregator instance.  With this code it is very easy to bind Menus, Buttons and the other WPF elements that implement the 'Command' in XAML to an MVVM class.  An example of the XAML is:

 <MenuItem Header="E_xit" Command="{Binding ExitMenuCommand}"  />

The MVVM property is:

        public ICommand ExitMenuCommand       

 { 

            get             

    {   if (_exitMenuCommand == null) 

                   _exitMenuCommand = new MilviaSystems.Common.DirectAggregatorCommand<ExitMenuEvent>(_eventAggregator, EventNames.EXIT_EVENT, () => { return true; });

  return _exitMenuCommand; }

            set { }      

            }

All the coding can be done in a single line (which was my objective).

The following is the code for the two classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;

namespace MilviaSystems.Common
{
    /// <summary>
    /// Class to propogate events directly to a Prism event aggregator.
    /// This class will 'publish' an event to the event aggregator, thereby making it available to all subscribers of the
    /// specified event type
    /// </summary>
    /// <typeparam name="TEventType"></typeparam>
    public delegate bool DirectAggregatorCommandCanExecuteDelegate();
    public abstract class DirectAggregatorCommandBase : ICommand
    {
        protected readonly IEventAggregator _eventAggregator;
        #region ctor
        protected DirectAggregatorCommandBase(IEventAggregator eventAggregator)
        {
            _eventAggregator = eventAggregator;
        }
        #endregion
        #region ICommand Members
        public abstract bool CanExecute(object parameter);

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public abstract void Execute(object parameter);

        #endregion
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;

namespace MilviaSystems.Common
{
    /// <summary>
    /// This class implements ICommand (from DirectAggregatorCommandBase and then will automatically publish
    /// the TEventType in the Prism Event Aggregator.
    /// The eventPayload is sent to the event aggregator for use by the subscribing modules.
    /// canExecute should be either a delegate reference or a lambda for returning a predicate value for the UI
    /// </summary>
    /// <typeparam name="TEventType">The Event Type used by the Event Aggregator</typeparam>
    public class DirectAggregatorCommand<TEventType> : DirectAggregatorCommandBase where TEventType : CompositePresentationEvent<object>
    {
        DirectAggregatorCommandCanExecuteDelegate _canExecute;
        object _eventPayload;
        /// <summary>
        /// Class constructor
        /// </summary>
        /// <param name="eventAggregator">The singleton Prism EventAggregator for mediating messages between modules</param>
        /// <param name="eventPayload">An optional object for passing to the subscribers</param>
        /// <param name="canExecute">A predicate for enabling\disabling controls by WPF</param>
        public DirectAggregatorCommand(IEventAggregator eventAggregator, object eventPayload, DirectAggregatorCommandCanExecuteDelegate canExecute)
            : base(eventAggregator)
        {
            _canExecute = canExecute;
            _eventPayload = eventPayload;
        }
        public override bool CanExecute(object parameter)
        {
            if (_canExecute != null)
                return _canExecute();
            else
                throw new ArgumentNullException("canExecute");
        }

        public override void Execute(object parameter)
        {
            if (_eventAggregator == null)
                throw new ArgumentNullException("eventAggregator");

            _eventAggregator.GetEvent<TEventType>().Publish(_eventPayload);

        }
    }

}

Martin Reich