Video for this session: http://www.youtube.com/watch?v=jdiu_dH3z5k
Code for this session: https://github.com/xamarin/Seminars/tree/master/2012-12-13-MVVMCross/
An introduction to one approach for using dependency injection, unit testing and MVVM in cross-platform mobile C# development with Stuart Lodge
2. Presentation Model
Represent the state and behavior of the presentation
independently of the GUI controls used in the
interface.
http://martinfowler.com/eaaDev/PresentationModel.html
3. In 2005…
Model/View/ViewModel is a variation of
Model/View/Controller that is tailored for modern UI
development platforms where the View is the
responsibility of a designer rather than a classic
developer.
Tales from the Smart Client, John Grossman
http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx
4. Also in 2005…
• 10 years of dev – C++, C, VB, Java, JavaScript,
LISP, SmallTalk, Delphi, …
• A year off travelling
– from Argentina to Zambia
• DeveloperDeveloperDeveloper
• 1 conclusion:
6. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
7. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
10. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
11. ViewModels Public Properties
private bool _isSearching;
public bool IsSearching
{
get { return _isSearching; }
set
{
_isSearching = value;
RaisePropertyChanged("IsSearching");
}
}
12. For ViewModel Changes
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
public class PropertyChangedEventArgs : EventArgs
{
public string PropertyName { get; }
}
13. For Collections
public interface INotifyCollectionChanged
{
event NotifyCollectionChangedEventHandler CollectionChanged;
}
public enum NotifyCollectionChangedAction
{
Add, Remove, Replace, Move, Reset,
}
public class NotifyCollectionChangedEventArgs : EventArg
{
public NotifyCollectionChangedAction Action { get; }
public IList NewItems { get; }
public IList OldItems { get; }
public int NewStartingIndex { get; }
public int OldStartingIndex { get; }
}
14. For Actions
public interface ICommand
{
event EventHandler CanExecuteChanged;
bool CanExecute(object parameter);
void Execute(object parameter);
}
15. .Net Implementation
ICommand
Public Property Set
INotifyPropertyChanged
INotifyCollectionChanged
Public Property Get
16. Why?
To Enable
• Awesome UI and Data Development
• Unit Testing of code
• Large applications to have a common
architecture
• Different platforms can share code
17. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
19. Code evolution I
• Single Mono for Android Project
• Good separation of UI from ‘Model’ code
• Simple – it works
• But:
– No testing
– No testability
– Portability by cut/paste
20. Code Evolution 2
• MvvmCross Library switched in
– PCL code
– Formal DI/IoC used
• On UI:
– DataBinding arrived
– Code got much thinner!
– XML got bigger
• Not all win:
– External Dependencies got larger
– Code overall increased in size
23. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
25. Unit Testing
“I get paid for code that works, not for tests, so my
philosophy is to test as little as possible to reach a
given level of confidence.
…
When coding on a team, I modify my strategy to
carefully test code that we, collectively, tend to get
wrong.”
Kent Beck
http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests
26. Plugin – Native abstractions
1. Declare common functionality (an interface)
public interface IMvxComposeEmailTask
{
void ComposeEmail(string to, string cc, string subject, string body, bool isHtml);
}
2. Write platform specific implementations
public class MvxComposeEmailTask : MvxWindowsPhoneTask, IMvxComposeEmailTask
{
public void ComposeEmail(string to, string cc, string subject, string body, bool isHtml)
{
var task = new EmailComposeTask() { To = to, Subject = subject, Cc = cc, Body = body };
DoWithInvalidOperationProtection(task.Show);
}
}
3. In apps, use the interface and not the implementation
protected void ComposeEmail(string to, string subject, string body)
{
Cirrious.MvvmCross.Plugins.Email.PluginLoader.Instance.EnsureLoaded();
var task = this.GetService<IMvxComposeEmailTask>();
task.ComposeEmail(to, null, subject, body, false);
}
27. Sphero – Plugin Magic
• Plugin Magic
• Each Plugin:
– 1 PCL
– 1 Assembly per platform
28. Why?
To Enable
• Awesome UI and Data Development
• Unit Testing of code
• Large applications to have a common
architecture
• Different platforms can share code
29. What we’ll cover…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
42. What we’ve covered…
• MVVM Theory
• .Net MVVM
• A practical example – some code!
• Interface Driven Development
– Portable Class Libraries
– Unit Testing
– Plugins
• Some examples
43. To join in…
If you want to join in:
• Tool up
• Share
• Reuse
• Test
• Architect
46. C# - 1 Stack - Cloud to Mobile
Data Access
Business Logic
Presentation
Service Consumption Local Data/Services
Business Logic
UI Logic
WP7 iOS Droid Win8
47. Not as cool as dinosaurs
Data Access
Business Logic
Presentation
Service Consumption Local Data/Services
Business Logic
UI Logic
WP7 iOS Droid Win8
48. Some credits
Images from Wikipedia Commons:
• http://en.wikipedia.org/wiki/File:Macronaria_scrubbed_enh.jpg
• http://en.wikipedia.org/wiki/File:Human-
eoraptor_size_comparison%28v2%29.png
Diagrams from Java – ZK
• http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/MVVM
Sample projects as credited inline