Wednesday, December 28, 2011

Code snippet for MVVM Pattern


MVVM Pattern

Both WPF & SilverLight encourages MVVM Pattern.
Difference between MVP & MVVM Patterns:

MVP

  • View should have reference to presenter. Eg : Click 'Save' in view, calls appropriate presenter method.

  • Presenter should have reference of view(IView) Eg : Filling a grid in view.

MVVM

  • Reference between VM(Presenter) & View is not required.

  • Reference between View & VM(Presenter) is required(to set ICommand.DataBinding).

  • DTO should implement INotifyPropertyChanged.



Code snippet:
DelegateCommand.cs
/*
It inherits ICommand. It can be used as a generic hooking class throughout the project
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace WpfApplication1
{
public class DelegateCommand : ICommand
{
#region Constructors
public DelegateCommand(Action executeMethod, Func canExecuteMethod)
{
if (executeMethod == null)
{
throw new ArgumentNullException("executeMethod");
}
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}

#endregion

#region ICommand Members

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

bool ICommand.CanExecute(object parameter)
{
if (_canExecuteMethod != null)
{
return _canExecuteMethod();
}
return true;
}

void ICommand.Execute(object parameter)
{
if (_executeMethod != null)
{
_executeMethod();
}
}

#endregion

#region Data
private readonly Action _executeMethod = null;
private readonly Func _canExecuteMethod = null;
#endregion
}
}



ViewModel.cs
/*
Uses the generic DelegateCommand.cs to hook its appropriate functions Save & Close.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Globalization;

namespace WpfApplication1
{
public class ViewModel
{

static ViewModel()
{
}
private DelegateCommand saveCommand;
private DelegateCommand closeCommand;

public ICommand SaveCommand
{
get
{
if (saveCommand == null)
saveCommand = new DelegateCommand(new Action(SaveExecuted), new Func(SaveCanExecute));

return saveCommand;
}
}
public ICommand CloseCommand
{
get
{
if (closeCommand == null)
closeCommand = new DelegateCommand(new Action(CloseExecuted), new Func(CloseCanExecute));

return closeCommand;
}
}
public bool SaveCanExecute()
{
return true;
}

public void SaveExecuted()
{
MessageBox.Show("Delegate Save Command Handled!");
}
public bool CloseCanExecute()
{
return true;
}

public void CloseExecuted()
{
MessageBox.Show("Delegate Close Command Handled!");
}
}
}




View.xaml.cs
/*
Pls note the cs is clean from referencing codes which is the ultimate aim of MVVM pattern]
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Globalization;
namespace WpfApplication1
{
///


/// Interaction logic for Window3.xaml
///

public partial class Window3 : Window
{
public Window3()
{
InitializeComponent();
}
}
}