Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / WPF
Tip/Trick

Simple EventAggregator in WPF PRISM 4

Rate me:
Please Sign up or sign in to vote.
4.53/5 (10 votes)
10 May 2013CPOL2 min read 38.3K   1.1K   6   3
An implementation of Event Aggregator in WPF MVVM PRISM 4

Introduction

While playing with PRISM 4, I loved the logic of regions. But in MVVM vs. PRISM standards, you have to obey some rules. To fire a simple event from one region to another, there're lots of choices out there. One of them is Event Aggregator.

For my tiny trigger need, I decided to create easy to use class, based on Event Aggregator.

These points are important for me for the class:

  • This class should be very easy to use.
  • While writing the code, I want very simple line of code; trigger event from a region/view and catch it from another region/view.
  • And also, this class should not override the logic structure of MVVM and/or PRISM.

I hope you like this article and will be useful to you.

Background

To understand this article, you should have knowledge about WPF, MVVM and PRISM.

I also strongly recommend you to give it a time to read about PRISM documentation where you can access from:

Using the code

Note: I used NuGet Packages to reference necessary assemblies in solution.

Event Aggregator Class

The EventAggregator class is based on CompositePresentationEvent.

In base, we'll be using a global event handler. But this class will handle initialization process on itself. Only thing you'll do is to call its properties in your code.

Let's think about a little project. In this project, we have two regions. In first one there's a list box containing file names which read from local disc. We want to see the name of the file on second region while we click on list box.

First we'll create our event class. Let's name it to FileSelectedGlobalEvent. This class will not be static. But EventAggregator in that class will be static.

C#
class FileSelectedGlobalEvent : CompositePresentationEvent<string>
{
    private static readonly EventAggregator _eventAggregator;
    private static readonly FileSelectedGlobalEvent _event;

    static FileSelectedGlobalEvent()
    {
        _eventAggregator = new EventAggregator();
        _event = _eventAggregator.GetEvent<FileSelectedGlobalEvent>();
    }

    public static FileSelectedGlobalEvent Instance
    {
        get { return _event; }
    }
}

First, we're creating a static instance of EventAggregator. Then, by using EventAggregator's GetEvent method, we're creating CompositePresentationEvent from same class, which is also static. Now we have FileSelectedGlobalEvent. By a static property (let's name it "Instance") we can access events, without any create process in out code.

Note that, because we want to transfer file name to other region, we create the class with CompositePresentationEvent<string>. You can use your own class here.

Publisher Code

Let's assume that we have a view model, called FileListViewModel.

The code in XAML is:

XML
<ListBox ItemsSource="{Binding FileList}" SelectedItem="{Binding SelectedFile, Mode=TwoWay}" />

The ItemsSource property is bound to FileList and the SelectedItem property is bound to SelectedFile property with two way. So, when user selects from list, SelectedFile property's set will execute.

Let's see whats going on in SelectedFile property:

C#
public string SelectedFile
{
    get { return _selectedFile; }
    set
    {
        if (value == _selectedFile)
            return;

        _selectedFile = value;
        RaisePropertyChanged(() => SelectedFile);

        FileSelectedGlobalEvent.Instance.Publish(value);
    }
}

As you see, we only use single line of code to trigger event:

C#
FileSelectedGlobalEvent.Instance.Publish(value);

Subscriber Code

Let's look at the subscriber code. Subscription is made in construction of the view model class.

C#
class FileInfoViewModel : NotificationObject
{
    public FileInfoViewModel()
    {
        FileSelectedGlobalEvent.Instance.Subscribe(ProcessFile);
    }
    
    private void ProcessFile(string fileName)
    {
        var fileInfo = new FileInfo(Path.Combine(GlobalVariables.RootPath, fileName));

        FileName = fileName;
        CreatedDate = fileInfo.CreationTime;
        UpdatedDate = fileInfo.LastWriteTime;
    }
}

In construction, we call Subscribe method and delegate it to a method.

C#
FileSelectedGlobalEvent.Instance.Subscribe(ProcessFile);

Because of we used CompositePresentationEvent with string, ProcessFile takes string argument. You can use your own class here.

History

This is the first published version.

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)
Turkey Turkey
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionUseful and easy to understand Pin
NandyX10-Oct-15 3:56
NandyX10-Oct-15 3:56 
Suggestionnice idea! thx Pin
E1dar3-Jul-13 0:10
E1dar3-Jul-13 0:10 
based on your code i'v created base class for all compositeEvents

C#
public abstract class EventBase<TEvent, TPayload> : CompositePresentationEvent<TPayload> where TEvent : EventBase, new()
    {
        private static readonly Lazy<IEventAggregator> _eventAggregator 
            = new Lazy<IEventAggregator>(ServiceLocator.Current.GetInstance<IEventAggregator>);
        
        public static TEvent Instance
        {
            get { return _eventAggregator.Value.GetEvent<TEvent>(); }
        }
    }

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.