A lot of times, we think of using patterns in our Silverlight applications for implementing loose-coupling, modularity, reusability etc. Using MVVM/Prism can make this possible. Prism 4 has provided several features for implementing such type of applications. Typically Modularity is one of the most important segments in Prism. A Module contains application specific logic, models, views etc. We can say that our Prism enabled Silverlight application consist of several such Modules. In such cases, based upon a business requirement, it is necessary to establish communication between two Views of the same Module (intra-module) or two Views of different Modules. So the question is how we can achieve this.
If you are new to Prism 4, I would strongly suggest you first read my previous article Using Prism with Silverlight 4, where I have introduced Prism and explained some important concepts in Prism that we will using in this article.
If you have experience of implementing user controls and custom controls in Silverlight, then to establish communication between user or custom control to its container (e.g. UserControl (MainPage)), you need the ‘EventHandler’ delegate and a custom event is required to define using this delegate. This approach is generally used everywhere. One of the nice parts of this approach is that it allows implementing a Publish/Subscribe pattern. But to subscribe to the object by the subscriber, the subscriber object must be physically referred by the publisher object. This is typically a tightly coupled approach and not suitable for the loosely coupled applications.
In case of developing a composite application, Prism has provided a mechanism of ‘Event Aggregation’. This is used to establish communication between two loosely coupled components using Publisher/Subscriber mechanisms, without having the knowledge of each other. In this article I have explained its implementation between two Views inside the same module.
The class ‘EventAggregator’ provides mechanism using which there can be multiple publishers who publish multiple events, which further can be subscribed by multiple subscribers. This class implements ‘IEventAggregator’ interface and is responsible for keeping collection of events in the system.
The event aggregator makes use of one more class named ‘CompositPresentationEvent<T>’. This is responsible for maintaining the collection of subscribers and is responsible for event dispatching to these subscribers. This class requires the Payload type used for the successful event connection between Publisher and Subscriber.
Creating Silverlight 4 application for communication between Views using EventAggregator.
Step 1: Open VS2010 and create a blank solution. Name it as ‘SL4_Intra_View_EventAggregator’.
Step 2: In this solution, add a new Silverlight application and name it as ‘SL4_EventAggregator’. This will also create ‘SL4_EventAggregator.Web’ host project.
Step 3: Rename ‘MainPage.Xaml’ to ‘Shell.xaml’ and also rename the code-behind class type and the class type of the user control in Shell.Xaml. In this project add the following Prism 4 library references:
Remove the RootVisual code from Application_Startup method of the App.Xaml.cs file.
Step 4: In the same solution, add a new Silverlight application and name it as ‘SL4_MasterDetails_Views’. Make sure that this new project uses the same host projected created in Step 2. This application is the Module containing Services, Models, ViewModels, Controllers, and Views. This application also defines Events so that Department-Employee master details can be achieved. Remove ‘MainPage.xaml’ and also remove the RootVisual code form Application_Startup method of the App.Xaml.cs file.
Step 5: In this project, add the same Prism references of Step 3. Add the following folders in the project:
Step 6: In Models folder, add two new class files and name them as ‘Department.cs’ and ‘Employee.cs’ and write the following code in it:
The above two classes define models and also a relationship between Department and Employee class is established using ‘DeptName’ string property.
In the ‘AppServices’ folder add a new class file, name it as ‘ServiceInterfaceClass.cs’. This file defines the service interface and class implementing the interface.
Note: You can extend this to cal External WCF service. This code of the class file is as below:
Currently the above code is hard-coding the data.
Now it is time for us to define the Event for communication. In this Module, I want to establish communication between Department and Employee views. In the project, add a new class file of name ‘DepartmentSelectedEvent.cs’. The following is the event declaration syntax:
The event is declared using ‘CompositePresentationEvent’ class. The payload for the communication used is of the type ‘string’.
In the ‘ViewModel’ folder add two class files of the name ‘DepartmentListViewModel.cs’ and ‘DepartmentEmployeeViewModel.cs’.
The above class defines the CollectionView for the Departments using ICollectionView interface. The ‘deptSelected’ event is declared using ‘IEventAggregator’ interface. The two argument constructor of the class defines instance for the Service class created above using its interface (ICompanyService) and initialize the event using ‘IEventAggregator’ interface. The ‘Departments’ collection is filled using the service call from the constructor. The ‘CurrentChanged’ event of the ‘PagedCollectionView’ class is raised in the constructor which further publishes the ‘DepartmentSelected’ event using DeptName for the current selected Department form the collection, as shown below:
The constructor defines an instance of the Service class using its interface and fills employee records in the ‘Employees’ Collection View. The ‘SelectedDepartment’ property refreshes the ‘Employees’ collection based upon the DeptName selected.
In the Views folder add Views for UI creation. These views will be bound with its concern ViewModel.
DepartmentListView.xaml -> DepartmentListViewModel.cs
DepartmentEmployeeView.xaml -> DepartmentEmployeeViewModel.cs
The View is set with its DataContext using its concern ViewModel.
The above view has set its DataContext property to its concern View Model. One important class here is the ‘RegionContext’ class. This class is responsible to share the contextual information between the views hosted using ‘IRegion’ in ‘RegionManager’. So when the user selects any DeptName from the DepartmentListView, it will be updated in the DepartmentEmployeeView using SelectedDepartment property and the filtered Employees will be displayed in this View. This sharing will be handled using ‘RegionContext’ class.
In the Project, add a new class file and name it as ‘RegionNameConstants.cs’. This will define the string constants for the regions which will be defined by Shell.xaml in next forthcoming Steps.
In the AppController folder, add a new class file and name it as ‘ViewController.cs’. This defines a class to subscribe to the event published by the ‘DepartmentListViewModel’ on the ‘DepartmentListView’ and inject the ‘DepartmentEmployeeView’ in the Region.
Please go through carefully through the above code as it is very important. The above class defines the behavior of the views defined in the module. The constructor initializes Container, RegionManager, EventAggregator and the service. The published event is subscribed here. The Subscribe method is passed with the reference for the ‘DepartmentSelectedEvent’ method to which the string ‘DeptName’ is passed. The method gets the Department object based upon the DeptName. The region instance is specified using ‘REGION_DEPARTMENT_EMPLOYEE_DETAILS’. From this region the instance of ‘DepartmentEmployeeView’ is obtained. If this instance is null, then this view is added in the region or else it is activated. After this step the DataContext for the view is set using its View concern ViewModel. The Controller class is heart of the application.
In the project add new class file of name ‘ModuleInitializer.cs’. This file is used to initialize the module and register the Views inside the module in the specific regions.
Build the project and make sure that it is error free.
Step 7: Go to the ‘SL4_EventAggregator’ project and add a new folder in it of name ‘ViewModel’. This folder will contain class file of name ‘ApplicationShellViewModel.cs’, used to define the behavior for the Shell View.
Define the Shell.Xaml as below:
This defines regions for displaying views in it.
The Module we will be loading using XAML, so add a new xml file in the project and name it as ‘ModuleCatalog.xaml’.
Add the Bootstrapper class in the project as shown below:
In the Application_Startup of the App.Xaml.cs, write the following code:
Step 8: Run the application, the output will be as below:
Select the DeptName and the respective employee details will change
Conclusion: EventAggregator, is an excellent and easy way to implement patterns for implementing loosely coupled event based communication between Views provided by Prism.
The entire source code of this article can be downloaded over here