Upload
dvoituron
View
563
Download
3
Embed Size (px)
Citation preview
MVVM Light v5
v1.0
Ir Denis VOITURON
http://www.dvoituron.be
Pattern
MVVM Light - v1.0 2
ModelBusiness Logic
View
Presentation UI
ViewModel
Presentation Logic
Command
Binding
Method call
Event
MVVMMODEL VIEW VIEWMODEL
Pattern
MVVM Light - v1.0 3
ModelBusiness Logic
View
Presentation UI
ViewModel
Presentation Logic
Command
Binding
Method call
Event
Friend
LastNameFirstNameDateOfBirthImageUrl
ObservableObject
FriendPage
<Page DataContext="{Binding Friend}"><TextBlock Text="{Binding FullName}" /><TextBlock Text="{Binding Age}" /><Image Source="{Binding ImageSource}" />
</Page>
FriendViewModel
FullNameAgeImageSource
ViewModelBase
NuGet : MVVM Light Libraries Only (PCL)
MVVM Light v5
Toolkit to help MVVM developments◦ Windows Presentation Foundation (3.5, 4, 4.5, 4.5.1)
◦ Silverlight (4 and 5)
◦ Windows Phone (7.1, 8, 8.1 Silverlight, 8.1 RT)
◦ Windows Store (8, 8.1)
◦ Xamarin Android
◦ Xamarin iOS
◦ Xamarin Forms
Open Source project
Supported by Microsoft
MVVM Light - v1.0 4
MVVM Light
Fundamentals
Model - DataService
MVVM Light - v1.0 6
public interface IDataService{Task<Friend[]> GetFriendsAsync();
}
public class DataService : IDataService{
public async Task<Friend[]> GetFriendsAsync(){
...}
}
public class DesignDataService : IDataService{
public async Task<Friend[]> GetFriendsAsync(){
...}
}
Model
Model – Data Classes
MVVM Light - v1.0 7
public class Friend{
public string FirstName { get; set; }public string LastName { get; set; }public DateTime DateOfBirth { get; set; }public string ImageUrl { get; set; }
}
public class Friend : ObservableObject{
private string _firstName = String.Empty;public string FirstName{
get { return _firstName; }set{
Set(() => this.FirstName, ref _firstName, value); }
}
Model
IoC – Inversion of Control
MVVM Light - v1.0 8
public class MainViewModel{
public MainViewModel(){
_dataService = new DataService();}
}
public class MainViewModel{
public MainViewModel(IDataService dataservice){
_dataService = dataservice;}
}
DataService for Test, for Production, for Design, …
An IoC container is◦ Responsible to create services when needed.
◦ Responsible for injecting them.
◦ Responsible for caching the objects.
◦ And providing access to them.
View
Model
ViewModelLocator
MVVM Light - v1.0 9
public class ViewModelLocator{
static ViewModelLocator(){
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<MainViewModel>();}
public MainViewModel Main{
get{
return ServiceLocator.Current.GetInstance<MainViewModel>();}
}}
View
Model
ViewModelLocator
MVVM Light - v1.0 10
View
Model
public class MainViewModel : ViewModelBase{
public MainViewModel(Model.IDataService dataService){
}}
<Applicationx:Class="MyApplication.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:viewmodel="using:MyApplication.ViewModel"xmlns:local="using:MyApplication">
<Application.Resources><viewmodel:ViewModelLocator x:Key="Locator" />
</Application.Resources>
</Application>
<Page x:Class="MyApplication.View.MainPage"...DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
NotifyPropertyChanged
MVVM Light - v1.0 11
View
Model
public class Friend : ViewModelBase{
private string _firstName = String.Empty;public string FirstName{
get { return _firstName; }set{
Set(() => this.FirstName, ref _firstName, value); }
}
private bool _isWorking = false;public bool IsWorking{
get { return _isWorking; }set{
Set(ref _isWorking, value); }
}
RelayCommand
MVVM Light - v1.0 12
private RelayCommand<FriendItem> _displayDetailCommand;
private void ExecuteDisplayDetailCommand(FriendItem item){Messenger.Default.Send<FriendItem>(item);_navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY, item.ID);
}
private void ExecuteDisplayDetailCommand(FriendItem item){
Messenger.Default.Send<FriendItem>(item);_navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY,
item.ID);}
private bool CanExecuteDisplayDetailCommand(FriendItem item){
return true;}
Navigation & Dialog
MVVM Light - v1.0 13
View
Model
public class ViewModelLocator{
public const string DAYDETAIL_PAGEKEY = "DayDetailPage";
static ViewModelLocator(){
...
// NavigationServiceSimpleIoc.Default.Register<INavigationService>(() =>{
var navigationService = new Model.NavigationService();navigationService.Configure(DAYDETAIL_PAGEKEY, typeof(View.DayDetailPage));navigationService.Configure(SEARCH_PAGEKEY, typeof(View.SearchPage));navigationService.Configure(TIMEDETAIL_PAGEKEY, typeof(View.TimeDetailView));return navigationService;
});
// DialogServiceSimpleIoc.Default.Register<IDialogService>(() =>{
return new DialogService();});...
}}
navigation.NavigateTo(ViewModelLocator.DAYDETAIL_PAGEKEY, e.Date);
View
ModelNavigation between ViewModels
In Source ViewModel
◦ Call NavigateTo method
In Target ViewModel
◦ Implement INavigableViewModel
◦ Override Page.OnNavigateTo
MVVM Light - v1.0 14
public interface INavigableViewModel{
void Activate(object parameter);void Deactivate(object parameter);
}
navigation.NavigateTo(ViewModelLocator.DAYDETAIL_PAGEKEY, e.Date);
protected override void OnNavigatedTo(NavigationEventArgs e){
base.OnNavigatedTo(e);
var navigableViewModel = this.DataContext as Model.INavigableViewModel;if (navigableViewModel != null)
navigableViewModel.Activate(e.Parameter);}
protected override void OnNavigatedFrom(NavigationEventArgs e){
base.OnNavigatedFrom(e);
var navigableViewModel = this.DataContext as Model.INavigableViewModel;if (navigableViewModel != null)
navigableViewModel.Deactivate(e.Parameter);}
Dialog from ViewModel
To display a dialog message, use
DialogService registered in
ViewModelLocator
MVVM Light - v1.0 15
View
Model
await _dialogService.ShowMessage("Let's go to the friend detail.", "Title", "OK", () =>{
// This code will be executed after OK click.});
await _dialogService.ShowMessage("Continue?", "Title", "OK", "Cancel", (ok) => {
if (ok){
_navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY, _selectedItem.ID);
}});
Async
CheckBeginInvokeOnUI
MVVM Light - v1.0 16
View
Model
public async Task LoadDataAsync(){
await Task.Run(async () =>{
var data = await _dataService.GetMyDataAsync();
DispatcherHelper.CheckBeginInvokeOnUI(() =>{
this.Items.AddRange(data);...
});});
}
public sealed partial class App : Application{
protected override void OnLaunched(LaunchActivatedEventArgs e){
DispatcherHelper.Initialize();...
InDesignMode, don’t user asynchronous tasks
DataContext
From ViewModel Locator
◦ If constructor of ViewModel use only
IoC parameters.
MVVM Light - v1.0 17
View
<Page x:Class="MyApplication.View.MainPage"...DataContext="{Binding Path=Main, Source={StaticResource Locator}}">
public class MainViewModel : ViewModelBase{public MainViewModel(IDataService dataService, INavigationService navigationService){
...}
}
DataContext
From Designer Creator
◦ If IoC Locator can not find the correct constructor
MVVM Light - v1.0 18
View
#if DEBUG/// <summary>/// This constructor is used in the Windows Phone app at design time,/// for the Blend visual designer./// </summary>public DetailViewModel() : this(SimpleIoc.Default.GetInstance<Model.IDataService>(),
SimpleIoc.Default.GetInstance<INavigationService>(), 0)
{...
}#endif
<Page x:Class="MyApplication.View.DetailPage"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"...xmlns:vm="using:MyApplication.ViewModel"d:DataContext="{d:DesignInstance Type=vm:DetailViewModel,
IsDesignTimeCreatable=True}">
public DetailViewModel(IDataService dataService, INavigationService navigationService, int id){
...
MVVM Light
Design Mode
Design Mode
Drawing UI with Visual Studio (Blend)
MVVM Light - v1.0 20
DataService
DesignDataService
MVVM Light - v1.0 21
public class DesignDataService : IDataService{
private List<Friend> _friends = new List<Friend>();
public DesignDataService(){
_friends.Add(new Friend() { LastName = "Voituron", FirstName = "Denis", ... });_friends.Add(new Friend() { LastName = "Dubois", FirstName = "Anne", ... });
...}
}
Model
Navigation
DesignNavigationService
MVVM Light - v1.0 22
public class DesignNavigationService : INavigationService{
public string CurrentPageKey{
get{
Debug.WriteLine("DesignNavigationService.CurrentPageKey");return String.Empty;
}}
public void GoBack(){
Debug.WriteLine("DesignNavigationService.GoBack()");}
public void NavigateTo(string pageKey, object parameter){
Debug.WriteLine(String.Format("DesignNavigationService.NavigateTo(\"{0}\", {1})", pageKey, parameter.ToString()));
}
public void NavigateTo(string pageKey){
Debug.WriteLine(String.Format("DesignNavigationService.NavigateTo(\"{0}\")", pageKey));}
}
Model
Dialog
DesignDialogService
MVVM Light - v1.0 23
public class DesignDialogService : IDialogService{
public System.Threading.Tasks.Task ShowError(Exception error, string title, string buttonText, Action afterHideCallback)
{throw new NotImplementedException();
}
public System.Threading.Tasks.Task ShowError(string message, string title, string buttonText, Action afterHideCallback)
{throw new NotImplementedException();
}
...
}
Model
ViewModelLocator
MVVM Light - v1.0 24
public class ViewModelLocator{
static ViewModelLocator(){
if (ViewModelBase.IsInDesignModeStatic){
DispatcherHelper.Initialize();
// DataService, Navigation and DialogSimpleIoc.Default.Register<IDataService>(() => new DesignDataService());SimpleIoc.Default.Register<INavigationService>(() => new DesignNavigationService());SimpleIoc.Default.Register<IDialogService>(() => new DesignDialogService());
// ViewModelsSimpleIoc.Default.Register<FriendViewModel>();
}else{
}}
}
View
Model
MVVM Light
Best Practices
Objectives
Define a manageable structure
Create Design data to draw UI easier
Create a DataService class to centralize all
external requests
Use always asynchronous operations
Display a working progress bar
MVVM Light - v1.0 26
Universal project
Create Blank App (Universal App)
Add NuGet Packages for Solution
Select MVVM Light Libraries Only (PCL)◦ WPF4.5 (and 4.5.1)
◦ Windows Phone (Silverlight) 8
◦ Windows Phone (Silverlight) 8.1
◦ Windows Phone (RT) 8.1
◦ Windows Store (RT) 8 and 8.1
◦ Xamarin Android
◦ Xamarin iOS
◦ PCL (for class libraries)
MVVM Light - v1.0 27
Universal Project
Shared
Design
DesignDataService
DesignDialogService
DesignNavigationService
Helpers
Extensions
VisualTreeHelper
Model
DataService
IDataService
INavigableViewModel
NavigationService
Friend
ViewModel
Friend
FriendViewModel
ViewModelLocator
Project Structure
MVVM Light - v1.0 28
WindowsPhone
Assets
Logo.png
Controls
SampleControl
View
FriendPage
Windows
Assets
Logo.png
Controls
SampleControl
View
FriendPage
Asynchronous
IDataServices
DesignDataService
MVVM Light - v1.0 29
public interface IDataService{
Task<Friend[]> GetFriendsAsync();}
public class DesignDataService : Model.IDataService{
List<Model.Friend> _friends = new List<Model.Friend>();
public DesignDataService(){
_friends.Add(new Model.Friend() { FriendID = 1, LastName = "Voituron", ... _friends.Add(new Model.Friend() { FriendID = 2, LastName = "Dubois", ...
}
#pragma warning disable 1998 // Supress warning "This async method lacks 'await' op."
public async Task<Model.Friend[]> GetFriendsAsync(){
return _friends.ToArray();}
#pragma warning restore 1998}
Asynchronous
ViewModel
MVVM Light - v1.0 30
public async void LoadDataAsync(){
this.IsWorking = true;
if (this.IsInDesignMode){
var data = await _dataService.GetFriendsAsync();this.Friends.AddRange(data);return;
}else{
await Task.Run(async () =>{
var data = await _dataService.GetFriendsAsync();DispatcherHelper.CheckBeginInvokeOnUI(() =>{
this.Friends.AddRange(data);});
});}
this.IsWorking = false;}
MVVM Light
References
References
http://www.mvvmlight.net/doc
http://www.spikie.be/blog/post/2013/04/12/10-
things-you-might-have-missed-about-MVVM-
Light.aspx
http://developer.nokia.com/community/wiki/How_to
_use_MVVM_Light_Toolkit_for_Windows_Phone
https://marcominerva.wordpress.com
https://github.com/dvoituron/SampleMvvmLight
MVVM Light - v1.0 32