Date post: | 10-May-2015 |
Category: |
Technology |
Upload: | paul-stovell |
View: | 10,027 times |
Download: | 3 times |
Real-world MVVM in WPFPaul Stovell
Senior ConsultantTechnical specialist: WPF
Agenda
Part 1: Introducing MVVM• Refactoring to MVVM• Unit testing MVVM• Commands
Part 2: Formalizing MVVM• History• Model-View-ViewModel• ViewModel-First
Part 3: Playing with Others• Navigation• Composition• Communication
About You
• Awesome coder• Know some WPF• Love binding!
This is you...
Introducing MVVMPART 1
Demo
Refactoring to MVVM
Demo
Unit testing MVVM
What did we just do?
• Employee = the Model• SearchView.xaml = the View• SearchViewModel = the ViewModel
Demo
Using Commands
Demo
New requirement: search-as-you-type
Formalizing MVVMPART 2
History
Martin Fowler
John Gossman
MVVM
Presentation Model
Model-View-ViewModel
View ViewModel External services
CommandsMethods
public void Search(){}
ICommand Search { get;set; }
void Button_Click(...){ viewModel.Search();}
<Button Command="{Binding Search}" />
Properties
Events
Model-View-ViewModel
View ViewModel External services
CommandsMethods
public string SearchText { get { ... } set { ... Search(); }}
<TextBox Text="{Binding SearchText}" />
Properties
Events
Model-View-ViewModel
View ViewModel External services
CommandsMethods
public event EventArgs SessionClosed;
viewModel.SessionClosed += (s,e) => Close();
Properties
Events
ViewModel-First MVVM
View ViewModel External services
CommandsMethods
View.Close();
ViewModel.Search();
Properties
Events
ViewModel-First MVVM
View ViewModel External services
CommandsMethods
public event EventHandler SessionClosed;
public event EventHandler SearchRequested;
Properties
Events
Model-View-Presenter
View Presenter External services
Methods
public event EventHandler SearchRequested;
Eventsprivate void View_SearchRequested(...){ // Do search}
Model-View-Presenter
View Presenter External services
Methods
View.ShowResults(results);
public void ShowResults(List<SearchResult> results){ listBox1.ItemsSource = results;}
Events
The Model
• Service messages/DTO’s• Domain entities/value objects• DataSets• LINQ to SQL objects
Or:
• View-specific objects mapped from above
Instantiation and wire-up
public CalculatorView(){ InitializeComponent(); DataContext = new CalculatorViewModel(); }
• Internal creation:
Instantiation and wire-up
public CalculatorView(CalculatorViewModel model){ InitializeComponent(); DataContext = model; }
• ViewModel as a dependency:
var viewModel = new CalculatorViewModel();var view = new CalculatorView(viewModel);
Instantiation and wire-up
<UserControl ...> <UserControl.DataContext> <local:CalculatorViewModel /> </UserControl.DataContext>
• ViewModel via XAML:
Instantiation and wire-up
• 5 more ways:http://is.gd/dv7aN
Playing with OthersPART 3
Navigation
1. INavigator.Navigate(...)2. Event
View+ViewModel
View
ViewModel
URI
Demo
• Adding navigation with Magellan
Composition
Shell ViewModel
Search ViewModel
Weather ViewModel
ShellSearch
Weather
Composition
Order ListTop Region
Bottom Region
Bottom-Up
Search Weather
Infrastructure
1. Resolve
2. Place
Inter-view Communication
Standard .NET events
Search View Model
Results View Model
Criteria View Model
1. Child model raises event2. Parent model forwards
event
Inter-view Communication
Results ViewModel
Criteria ViewModel
Hub
Publish Handle
Advert ViewModel
Handle
Recent Searches
ViewModel
Publish
Mediator (e.g., Prism EventAggregator)
bus.Publish(new SearchMessage(searchText));
bus.Subscribe<SearchMessage>(HandleSearch);
Conclusion
• MVVM is about separation of concerns– View has UI-specific code– VM has behaviour and state– Behaviour = methods/commands– State = properties
• Separation of concerns makes code easy to test
• It’s easy: just one extra class!
What’s next?
• Inversion of Control containers• Modular applications• Pub/sub messaging• Inductive user interfaces• p&p Prism
Links
• MVVM Light: http://is.gd/duX2Q• Caliburn: http://is.gd/duX5L• More: http://is.gd/duWWG• Magellan: http://is.gd/duX70• Reuxables: http://is.gd/duX8G
DeveloperDeveloperDeveloper! Events would not be possibleWith out the generous support from our sponsors…
We would like to thank the following for their support: