MVVM Lights

Download MVVM Lights

Post on 15-Jul-2015




1 download

Embed Size (px)


<p>Training Title</p> <p>MVVM Light v5v1.0Ir Denis VOITURONhttp://www.dvoituron.be1PatternMVVM Light - v1.02Model</p> <p>Business LogicView</p> <p>Presentation UIViewModel</p> <p>Presentation LogicCommandBindingMethod callEventMVVMMODEL VIEW VIEWMODELPatternMVVM Light - v1.03Model</p> <p>Business LogicView</p> <p>Presentation UIViewModel</p> <p>Presentation LogicCommandBindingMethod callEventFriendLastNameFirstNameDateOfBirthImageUrlObservableObjectFriendPage</p> <p>FriendViewModelFullNameAgeImageSourceViewModelBaseNuGet : MVVM Light Libraries Only (PCL)MVVM Light v5Toolkit to help MVVM developmentsWindows 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 AndroidXamarin iOSXamarin FormsOpen Source projectSupported by MicrosoftMVVM Light - v1.04MVVM LightFundamentalsModel - DataServiceMVVM Light - v1.06public interface IDataService{ Task GetFriendsAsync();}public class DataService : IDataService{ public async Task GetFriendsAsync() { ... }}public class DesignDataService : IDataService{ public async Task GetFriendsAsync() { ... }}Model6Model Data ClassesMVVM Light - v1.07public 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(() =&gt; this.FirstName, ref _firstName, value); } }ModelIoC Inversion of ControlMVVM Light - v1.08public 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 isResponsible to create services when needed.Responsible for injecting them.Responsible for caching the objects.And providing access to them.ViewModelViewModelLocatorMVVM Light - v1.09 public class ViewModelLocator { static ViewModelLocator() { ServiceLocator.SetLocatorProvider(() =&gt; SimpleIoc.Default);</p> <p> SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); }</p> <p> public MainViewModel Main { get { return ServiceLocator.Current.GetInstance(); } } }ViewModelViewModelLocatorMVVM Light - v1.010ViewModelpublic class MainViewModel : ViewModelBase{ public MainViewModel(Model.IDataService dataService) { }}</p> <p>NotifyPropertyChangedMVVM Light - v1.011ViewModelpublic class Friend : ViewModelBase{ private string _firstName = String.Empty; public string FirstName { get { return _firstName; } set { Set(() =&gt; this.FirstName, ref _firstName, value); } }</p> <p> private bool _isWorking = false; public bool IsWorking { get { return _isWorking; } set { Set(ref _isWorking, value); } }RelayCommandMVVM Light - v1.012private RelayCommand _displayDetailCommand;private void ExecuteDisplayDetailCommand(FriendItem item){ Messenger.Default.Send(item); _navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY, item.ID);}private void ExecuteDisplayDetailCommand(FriendItem item){ Messenger.Default.Send(item); _navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY, item.ID);}private bool CanExecuteDisplayDetailCommand(FriendItem item){ return true;}Navigation &amp; DialogMVVM Light - v1.013ViewModel public class ViewModelLocator { public const string DAYDETAIL_PAGEKEY = "DayDetailPage";</p> <p> static ViewModelLocator() { ...</p> <p> // NavigationService SimpleIoc.Default.Register(() =&gt; { 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; });</p> <p> // DialogService SimpleIoc.Default.Register(() =&gt; { return new DialogService(); }); ... }}navigation.NavigateTo(ViewModelLocator.DAYDETAIL_PAGEKEY, e.Date);ViewModelNavigation between ViewModelsIn Source ViewModelCall NavigateTo method</p> <p>In Target ViewModelImplement INavigableViewModelOverride Page.OnNavigateTo MVVM Light - v1.014public 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);</p> <p> var navigableViewModel = this.DataContext as Model.INavigableViewModel; if (navigableViewModel != null) navigableViewModel.Activate(e.Parameter);}protected override void OnNavigatedFrom(NavigationEventArgs e){ base.OnNavigatedFrom(e);</p> <p> var navigableViewModel = this.DataContext as Model.INavigableViewModel; if (navigableViewModel != null) navigableViewModel.Deactivate(e.Parameter);}Dialog from ViewModelTo display a dialog message, use DialogService registered in ViewModelLocatorMVVM Light - v1.015ViewModelawait _dialogService.ShowMessage("Let's go to the friend detail.", "Title", "OK", () =&gt;{ // This code will be executed after OK click.});await _dialogService.ShowMessage("Continue?", "Title", "OK", "Cancel", (ok) =&gt; { if (ok) { _navigationService.NavigateTo(ViewModel.ViewModelLocator.FRIENDDETAIL_PAGEKEY, _selectedItem.ID); }});AsyncCheckBeginInvokeOnUIMVVM Light - v1.016ViewModelpublic async Task LoadDataAsync(){ await Task.Run(async () =&gt; { var data = await _dataService.GetMyDataAsync(); DispatcherHelper.CheckBeginInvokeOnUI(() =&gt; { this.Items.AddRange(data); ... }); });}public sealed partial class App : Application{ protected override void OnLaunched(LaunchActivatedEventArgs e) { DispatcherHelper.Initialize(); ...InDesignMode, dont user asynchronous tasksDataContextFrom ViewModel LocatorIf constructor of ViewModel use onlyIoC parameters.MVVM Light - v1.017View</p> <p>public class MainViewModel : ViewModelBase{ public MainViewModel(IDataService dataService, INavigationService navigationService) { ... }}DataContextFrom Designer CreatorIf IoC Locator can not find the correct constructorMVVM Light - v1.018View#if DEBUG /// /// This constructor is used in the Windows Phone app at design time, /// for the Blend visual designer. /// public DetailViewModel() : this(SimpleIoc.Default.GetInstance(), SimpleIoc.Default.GetInstance(), 0) { ... }#endif</p> <p>public DetailViewModel(IDataService dataService, INavigationService navigationService, int id) { ...MVVM LightDesign ModeDesign ModeDrawing UI with Visual Studio (Blend)MVVM Light - v1.020</p> <p>DataServiceDesignDataServiceMVVM Light - v1.021 public class DesignDataService : IDataService { private List _friends = new List(); public DesignDataService() { _friends.Add(new Friend() { LastName = "Voituron", FirstName = "Denis", ... }); _friends.Add(new Friend() { LastName = "Dubois", FirstName = "Anne", ... });</p> <p> ... }}ModelNavigationDesignNavigationServiceMVVM Light - v1.022public class DesignNavigationService : INavigationService{ public string CurrentPageKey { get { Debug.WriteLine("DesignNavigationService.CurrentPageKey"); return String.Empty; } }</p> <p> public void GoBack() { Debug.WriteLine("DesignNavigationService.GoBack()"); }</p> <p> public void NavigateTo(string pageKey, object parameter) { Debug.WriteLine(String.Format("DesignNavigationService.NavigateTo(\"{0}\", {1})", pageKey, parameter.ToString())); }</p> <p> public void NavigateTo(string pageKey) { Debug.WriteLine(String.Format("DesignNavigationService.NavigateTo(\"{0}\")", pageKey)); }}ModelDialogDesignDialogServiceMVVM Light - v1.023public class DesignDialogService : IDialogService{ public System.Threading.Tasks.Task ShowError(Exception error, string title, string buttonText, Action afterHideCallback) { throw new NotImplementedException(); }</p> <p> public System.Threading.Tasks.Task ShowError(string message, string title, string buttonText, Action afterHideCallback) { throw new NotImplementedException(); }</p> <p> ...</p> <p>}ModelViewModelLocatorMVVM Light - v1.024 public class ViewModelLocator { static ViewModelLocator() { if (ViewModelBase.IsInDesignModeStatic) { DispatcherHelper.Initialize();</p> <p> // DataService, Navigation and Dialog SimpleIoc.Default.Register(() =&gt; new DesignDataService()); SimpleIoc.Default.Register(() =&gt; new DesignNavigationService()); SimpleIoc.Default.Register(() =&gt; new DesignDialogService());</p> <p> // ViewModels SimpleIoc.Default.Register(); } else {</p> <p> } }}ViewModelMVVM LightBest PracticesObjectivesDefine a manageable structureCreate Design data to draw UI easierCreate a DataService class to centralize all external requestsUse always asynchronous operationsDisplay a working progress barMVVM Light - v1.026Universal projectCreate Blank App (Universal App)Add NuGet Packages for SolutionSelect MVVM Light Libraries Only (PCL)WPF4.5 (and 4.5.1)Windows Phone (Silverlight) 8Windows Phone (Silverlight) 8.1Windows Phone (RT) 8.1Windows Store (RT) 8 and 8.1Xamarin AndroidXamarin iOSPCL (for class libraries)MVVM Light - v1.027Universal ProjectSharedDesign DesignDataService DesignDialogService DesignNavigationServiceHelpers Extensions VisualTreeHelperModel DataService IDataService INavigableViewModel NavigationService FriendViewModel Friend FriendViewModel ViewModelLocator</p> <p>Project StructureMVVM Light - v1.028WindowsPhoneAssets Logo.pngControls SampleControlView FriendPageWindowsAssets Logo.pngControls SampleControlView FriendPageAsynchronousIDataServices</p> <p>DesignDataServiceMVVM Light - v1.029public interface IDataService{ Task GetFriendsAsync();}public class DesignDataService : Model.IDataService{ List _friends = new List();</p> <p> public DesignDataService() { _friends.Add(new Model.Friend() { FriendID = 1, LastName = "Voituron", ... _friends.Add(new Model.Friend() { FriendID = 2, LastName = "Dubois", ... }</p> <p> #pragma warning disable 1998 // Supress warning "This async method lacks 'await' op."</p> <p> public async Task GetFriendsAsync() { return _friends.ToArray(); }</p> <p> #pragma warning restore 1998}AsynchronousViewModelMVVM Light - v1.030public async void LoadDataAsync(){ this.IsWorking = true;</p> <p> if (this.IsInDesignMode) { var data = await _dataService.GetFriendsAsync(); this.Friends.AddRange(data); return; } else { await Task.Run(async () =&gt; { var data = await _dataService.GetFriendsAsync(); DispatcherHelper.CheckBeginInvokeOnUI(() =&gt; { this.Friends.AddRange(data); }); }); }</p> <p> this.IsWorking = false;}MVVM LightReferencesReferences </p> <p> MVVM Light - v1.032</p>