Simple MVVM Walkthrough – Refactored
Posted
by Sean Feldman
on ASP.net Weblogs
See other posts from ASP.net Weblogs
or by Sean Feldman
Published on Wed, 12 Jan 2011 07:07:00 GMT
Indexed on
2011/01/12
7:54 UTC
Read the original article
Hit count: 408
wpf
JR has put together a good introduction post into MVVM pattern. I love kick start examples that serve the purpose well. And even more than that I love examples that also can pass the real world projects check. So I took the sample code and refactored it slightly for a few aspects that a lot of developers might raise a brow.
Michael has mentioned model (entity) visibility from view. I agree on that. A few other items that don’t settle are using property names as string (magical strings) and Saver class internal casting of a parameter (custom code for each Saver command).
Fixing a property names usage is a straight forward exercise – leverage expressions. Something simple like this would do the initial job:
class PropertyOf<T>
{
public static string Resolve(Expression<Func<T, object>> expression)
{
var member = expression.Body as MemberExpression;
return member.Member.Name;
}
}With this, refactoring of properties names becomes an easy task, with confidence that an old property name string will not get left behind. An updated Invoice would look like this:
public class Invoice : INotifyPropertyChanged
{
private int id;
private string receiver;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public int Id
{
get { return id; }
set
{
if (id != value)
{
id = value;
OnPropertyChanged(PropertyOf<Invoice>.Resolve(x => x.Id));
}
}
}
public string Receiver
{
get { return receiver; }
set
{
receiver = value;
OnPropertyChanged(PropertyOf<Invoice>.Resolve(x => x.Receiver));
}
}
}For the saver, I decided to change it a little so now it becomes a “view-model agnostic” command, one that can be used for multiple commands/view-models. Updated Saver code now accepts an action at construction time and executes that action. No more black magic ![]()
internal class Command : ICommand
{
private readonly Action executeAction;
public Command(Action executeAction)
{
this.executeAction = executeAction;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
// no more black magic
executeAction();
}
}Change in InvoiceViewModel is instantiation of Saver command and execution action for the specific command.
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
saveCommand = new Command(ExecuteAction);
return saveCommand;
}
set { saveCommand = value; }
}
private void ExecuteAction()
{
DisplayMessage = string.Format("Thanks for creating invoice: {0} {1}", Invoice.Id, Invoice.Receiver);
}This way internal knowledge of InvoiceViewModel remains in InvoiceViewModel and Command (ex-Saver) is view-model agnostic.
Now the sample is not only a good introduction, but also has some practicality in it. My 5 cents on the subject.
Sample code MvvmSimple2.zip
© ASP.net Weblogs or respective owner