Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Présentation et bonnes pratiques du pattern MVVM - MIC Belgique

721 views

Published on

Le Model View ViewModel (MVVM) est une architecture et une méthode de conception utilisée dans le génie logiciel. Apparu en 2004, MVVM est adapté pour le développement des applications basées sur les technologies Windows (desktop, tablette ou mobile), mais également Web/HTML5. Cette méthode permet de séparer la vue de la logique et de l'accès aux données en accentuant les principes de binding et d’événement. Une bonne vue générale a été donnée par Laurent Bugnion, le père du MVVMLight, dans le podcast #11 de DevApps (http://devapps.be/podcast/11).

http://www.meetup.com/fr-FR/micbelgique/events/228368909/?eventId=228368909

Published in: Technology
  • If you have any problems with writing, feel free to ask our writers for help! ⇒ www.HelpWriting.net ⇐ is ready to help with any kind of academic writing!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Unlock Her Legs is your passage way to a life full of loving and sex... read more ... ◆◆◆ http://t.cn/AiurDrZp
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Présentation et bonnes pratiques du pattern MVVM - MIC Belgique

  1. 1. 1
  2. 2. 2 Denis Voituron Civil engineer (Mons) Company founder Developer: VB3, VB.Net, C# .Net Software Architect (Trasys) Blogger Speaker (DevApps.be)
  3. 3. 3 • Introduction • Getting Started • Services and DesignServices • Localization • Commands • Messenger • Unit Tests and TestServices
  4. 4. 4
  5. 5. 5
  6. 6. 6 Pattern Model Business Logic View Presentation UI ViewModel Presentation Logic Command Binding Method call Event MVVMMODEL VIEW VIEWMODEL
  7. 7. 7 Pattern Model Business Logic View Presentation UI ViewModel Presentation Logic Command Binding Method call Event Friend FirstName LastName DateOfBirth PictureUrl ObservableObject FriendPage <Page DataContext="{Binding ViewModel}"> <TextBlock Text="{Binding FullName}" /> <TextBlock Text="{Binding Age}" /> <Image Source="{Binding Photo}" /> </Page> FriendViewModel FullName Age Photo ViewModelBase
  8. 8. 8 • Code behind is not always bad, but can complicate things. • MVVM is a variation of MVC. • The goal is to decouple the View from the Model. • Easier to maintain. • Easier to test • Allow to create design time data. @LBugnion
  9. 9. 9 MVVM Light v5 Toolkit to help MVVM developments Open Source project Supported by Microsoft http://www.mvvmlight.net
  10. 10. 10
  11. 11. 11
  12. 12. 12 Window Dialog Page View
  13. 13. 13 public class Friend { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Picture { get; set; } public string Location { get; set; } public string Message { 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
  14. 14. 14 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
  15. 15. 15 public class MainViewModel { public MainViewModel() { _dataService = new DataService(); } } public class MainViewModel { public MainViewModel(IDataService dataservice) { _dataService = dataservice; } } DataService for Test, for Production, for Design, …
  16. 16. 16 public class ViewModelLocator { public ViewModelLocator() { // SimpleIoC ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); // Models if (ViewModelBase.IsInDesignModeStatic) SimpleIoc.Default.Register<IDataService, DataService>(); else SimpleIoc.Default.Register<IDataService, DesignDataService>(); // ViewModels SimpleIoc.Default.Register<ViewModels.MainViewModel>(); } } View Model <Application xmlns:locator="using:SampleMvvmLight.ViewModels" ... > <Application.Resources> <locator:ViewModelLocator x:Key="ViewModelLocator" /> </Application.Resources> </Application>
  17. 17. 17 public abstract class ViewModelBase : GalaSoft.MvvmLight.ViewModelBase { // Default constructor used by the Design or Production Mode public ViewModelBase() : this(ServiceLocator.Current.GetInstance<Models.IDataService>(), ServiceLocator.Current.GetInstance<IDialogService>(), ServiceLocator.Current.GetInstance<INavigationService>()) { if (ViewModelBase.IsInDesignModeStatic) OnLoadedAsync(); } // Default constructor with all usable services protected ViewModelBase(IDataService dataservice, IDialogService dialogService, INavigationService navigationService) { this.DateService = dataservice; this.DialogService = dialogService; this.NavigationService = navigationService; } } View Model
  18. 18. 18 Snippet ‘mvvminpcsetlambda’ View Model public class MainViewModel : ViewModelBase { protected async override Task OnLoadedAsync() { this.Friends = await this.DateService.GetFriendsAsync(); } private Friend[] _friends = null; public Friend[] Friends { get { return _friends; } set { Set(() => Friends, ref _friends, value); } } }
  19. 19. 19 private ViewModels.MainViewModel ViewModel { get { return ((MainViewModel)Resources["ViewModel"]); } } View <Page xmlns:vm="using:SampleMvvmLight.ViewModels"> <!-- Create a new instance of the associated ViewModel --> <Page.Resources> <vm:MainViewModel x:Key="ViewModel" /> </Page.Resources> <!-- Content --> <Grid DataContext="{StaticResource ViewModel}"> <ListView Margin="10,33,10,10" ItemsSource="{Binding Friends}" /> </Grid> </Page>
  20. 20. 20 Rules for views and view models User controls vs templated controls @ricosuter
  21. 21. 21 View model instantiation <MySubView DataContext="{Binding MySubViewModel}" /> <MySubView Project="{Binding SelectedProject}" /> public MyView() { InitializeComponent(); Loaded += async delegate { await ViewModel.OnLoaded(); }; Unloaded += async delegate { await ViewModel.OnUnloaded(); }; }
  22. 22. 22
  23. 23. 23 Interface for testing, designing and running Sample public interface IDataService { Task<Friend[]> GetFriendsAsync(); } public class DataService : IDataService { const string UrlBase = "http://xxx.azurewebsites.net/friends.aspx"; public async Task<Friend[]> GetFriendsAsync() { var client = new HttpClient(); string json = await client.GetStringAsync(new Uri(UrlBase)); var result = JsonConvert.DeserializeObject<ListOfFriends>(json); return result.Data.ToArray(); }
  24. 24. 24 SimpleIoc.Default.Register<IDialogService, DialogService>(); await this.DialogService.ShowMessage ("My message", "My title"); await this.DialogService.ShowMessageBox("My message", "My title"); await this.DialogService.ShowError(MyException, ...);
  25. 25. 25 private INavigationService CreateNavigationService() { var navigationService = new NavigationService(); navigationService.Configure(MAIN_PAGE, typeof(MainPage)); navigationService.Configure(DETAIL_PAGE, typeof(DetailPage)); return navigationService; } ... SimpleIoc.Default.Register<INavigationService>(() => CreateNavigationService()); public class NavigationService : INavigationService { public void NavigateTo<T>(string pageKey, T parameter) { ... } public void GoBack() { ... } }
  26. 26. 26 Navigate to the second page Retrieve parameters public class FirstViewModel : ViewModelBase { ... this.NavigationService.NavigateTo<string>(ViewModelLocator.DETAIL_PAGE, "ABC"); } public class SecondViewModel : ViewModelBase { public DetailViewModel() { this.NavigationRegistering<int>(); } protected async override Task OnNavigationFrom(object parameter) { this.Friend = await this.DateService.GetFriendAsync((int)parameter); } }
  27. 27. 27 Resource files • Resw Need a T4 file • Resx Configurable MyResources.Culture = new CultureInfo("fr"); CultureInfo.CurrentCulture = new CultureInfo("fr");
  28. 28. 28 The following prefixes or postfixes are recommended: (bigger projects, the keys should start with a module name. e.g. ‘Search_ButtonOK’) * * * * * * * * * * @ricosuter
  29. 29. 29
  30. 30. 30 Commands are instantiated in constructor. • Name "xxxCommand" • "xxxExecute" and "CanXxxExecute" public MainViewModel() { DisplayDetailCommand = new RelayCommand<Friend> (DisplayDetailExecute, CanDisplayDetailExecute); } public RelayCommand<Friend> DisplayDetailCommand { get; private set; } public void DisplayDetailExecute(Friend parameter) { ... } public bool CanDisplayDetailExecute(Friend parameter) { return true; } <Button Command="{Binding DisplayDetailCommand}" CommandParameter="{Binding SelectedFriend}" /> Snippet ‘mvvmrelaymethodcanexecute’
  31. 31. 31
  32. 32. 32 • It is an "event bus". • A message distribution system. • One default instance (Messenger.Default) @LBugnion
  33. 33. 33 Messenger.Default.Send<string>("Hello World"); Messenger.Default.Register<string> ( this, (message) => { ... } ); Messenger.Default.Unregister<string>(this);
  34. 34. 34
  35. 35. 35 • TestDataService • TestDialogService • TestNavigationService • TestServiceRegister public static void Registering() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register<IDataService, TestDataService>(); SimpleIoc.Default.Register<IDialogService, TestDialogService>(); SimpleIoc.Default.Register<INavigationService, TestNavigationService>(); }
  36. 36. 36 • Initialization • Test [TestClass] public class MainViewModelTests { [TestInitialize] public void Initialize() { TestServiceRegister.Registering(); } } [TestMethod] public async Task ComputeNumberOfFriends() { MainViewModel main = new MainViewModel(); await main.CallOnLoaded(); Assert.AreEqual(3, main.Friends.Length); }
  37. 37. 37
  38. 38. 38 • • • • • • • • •
  39. 39. 39 Ressources • • • • •

×