Tuesday, January 4, 2011

Silverlight, PRISM, MVVM, MEF – Part 1

The Model-View-ViewModel (MVVM) pattern helps you to cleanly separate the business and presentation logic of your application from its user interface (UI). The MVVM pattern helps you separate the presentation and business logic to be put into 3 main classes, VIEW, VIEW MODEL and MODEL.
In this post we’ll see the implementation of MVVM in prism using MEF for View and ViewModel discovery.  The class interactions used in this sample is as given below.

The model class in the sample contains data for the Employee object
public class Employee : BaseEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfJoining { get; set; }
    public string Designation { get; set; }
}

The EmployeeRepository class is used to query data about employees.
[Export(typeof(IEmployeeRepository))]
public class EmployeeRepository : Repository<Employee>, IEmployeeRepository
{
    public override System.Collections.Generic.IEnumerable<Employee> All()
    {
        return _context.Employees;
    }

    public override void Save(Employee entity)
    {
        //Save method
    }

    public override void Remove(Employee entity)
    {
        //Remove logic
    }
}

The repository instance will be resolved in the ViewModel class via the Import attribute.
[ImportingConstructor]
public EmployeeViewModel(IEmployeeRepository employeeRepository)
{
     _employeeRepository = employeeRepository;
     GetEmployees();
}
Implementing the View and ViewModel classes
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class EmployeeViewModel : NotificationObject
{
    [ImportingConstructor]
    public EmployeeViewModel(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
        GetEmployees();
    }

    private void GetEmployees()
    {
        Employees = new ObservableCollectionEmployee>(_employeeRepository.All());
    }

    public ObservableCollectionEmployee> Employees { get; set; }

    IEmployeeRepository _employeeRepository;

}

The ViewModel instance is resolved in the view the same way.
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class EmployeeView : UserControl
{
    [Import]
    public EmployeeViewModel ViewModel
    {
        set { DataContext = value; }
    }

    public EmployeeView()
    {
        InitializeComponent();
    }
}
The NonShared enumeration makes sure that singleton instance of view is not created. Now in the module controller class you can resolve this view instance and show it in the respective region when required. My code sample looks like.
[Import]
public EmployeeView EmployeeView { get; set; }           

[ImportingConstructor]
public EmployeeModule(IRegionManager regionManager)
{
    _regionManager = regionManager;
}

private void OnSearchAndViewClicked()
{
    _regionManager.AddToRegion("MainRegion", EmployeeView);
    _regionManager.Regions["MainRegion"].Activate(EmployeeView);
}
Final output

Next we’ll see how to implement commands and interactions between View and ViewModel via ICommand implementation.

6 comments:

Wenyonk said...

Very good example, thank you! Can you post the source code as you go through each part (Part 1).

teusje said...

source code would be nice indeed

Prajeesh said...

I'll create a codeplex project with the source code and share the link here. Unfortunately, I'm not able to attach the code in blogger :(

Ivan Padron said...

Can you please share me the source code?...

Thanks!

Prajeesh said...

Uploaded the code to codeplex...
http://blogsprajeesh.blogspot.com/2011/02/prism-mef-mvvm-toc.html

D. Bruno said...

Great work! Question, how would you fit Rx in this example?