From a3937e78da0cd1ee23df6599f8026f9590c2bc46 Mon Sep 17 00:00:00 2001 From: watsonb8 Date: Mon, 15 Jul 2019 15:03:59 -0400 Subject: [PATCH] Viewmodels are now maintained throughout the app lifecycle --- .../NavigationMenu/NavigationItem.cs | 2 + .../Design/Views/Artists/ArtistsViewModel.cs | 2 +- Aurora/Design/Views/BaseViewModel.cs | 8 +++ Aurora/Design/Views/MainView/MainView.xaml.cs | 53 ++++++++++++++++++- Aurora/Design/Views/MainView/MainViewModel.cs | 12 ++--- Aurora/Design/Views/Party/PartyView.xaml.cs | 1 - .../Design/Views/Profile/ProfileView.xaml.cs | 1 - Aurora/Design/Views/Songs/SongsView.xaml | 4 -- .../Views/Stations/StatiosnViewModel.cs | 2 +- 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Aurora/Design/Components/NavigationMenu/NavigationItem.cs b/Aurora/Design/Components/NavigationMenu/NavigationItem.cs index f2101c1..a697d09 100644 --- a/Aurora/Design/Components/NavigationMenu/NavigationItem.cs +++ b/Aurora/Design/Components/NavigationMenu/NavigationItem.cs @@ -17,5 +17,7 @@ namespace Aurora.Design.Components.NavigationMenu public string Group { get; set; } public Type TargetType { get; set; } + + public Type TargetViewModelType { get; set; } } } diff --git a/Aurora/Design/Views/Artists/ArtistsViewModel.cs b/Aurora/Design/Views/Artists/ArtistsViewModel.cs index e01cdd6..5ffd44a 100644 --- a/Aurora/Design/Views/Artists/ArtistsViewModel.cs +++ b/Aurora/Design/Views/Artists/ArtistsViewModel.cs @@ -1,7 +1,7 @@ using System; namespace Aurora.Design.Views.Artists { - public class ArtistsViewModel + public class ArtistsViewModel : BaseViewModel { public ArtistsViewModel() { diff --git a/Aurora/Design/Views/BaseViewModel.cs b/Aurora/Design/Views/BaseViewModel.cs index 8de444d..1f2afc8 100644 --- a/Aurora/Design/Views/BaseViewModel.cs +++ b/Aurora/Design/Views/BaseViewModel.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel; using System.Runtime.CompilerServices; +using System.Threading.Tasks; namespace Aurora.Design.Views { @@ -10,6 +11,13 @@ namespace Aurora.Design.Views { } + #region Lifecycle + public virtual void OnActive() { } + + public virtual void OnInactive() { } + + #endregion + #region INotifyPropertyChanged Implementation public bool SetProperty(ref T storage, T value, [CallerMemberName] string propertyName = null) { diff --git a/Aurora/Design/Views/MainView/MainView.xaml.cs b/Aurora/Design/Views/MainView/MainView.xaml.cs index d05174d..d2e6689 100644 --- a/Aurora/Design/Views/MainView/MainView.xaml.cs +++ b/Aurora/Design/Views/MainView/MainView.xaml.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +using System.Collections.Generic; using System.Linq; using Aurora.Design.Components.NavigationMenu; using Aurora.Design.Views.MainView; @@ -11,10 +12,14 @@ namespace Aurora.Design.Views.Main [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainView : MasterDetailPage { + private Dictionary _viewModels; + private BaseViewModel _lastViewModel; + public MainView() { InitializeComponent(); BindingContext = new MainViewModel(); + _viewModels = new Dictionary(); MasterPage.ListView.ItemSelected += ListView_ItemSelected; Appearing += OnAppearing; @@ -32,6 +37,33 @@ namespace Aurora.Design.Views.Main var view = (View)Activator.CreateInstance(item.TargetType); + //Check if we have an instantiated viewModel + BaseViewModel vm = new BaseViewModel(); + if (_viewModels.ContainsKey(item.Id)) + { + _viewModels.TryGetValue(item.Id, out vm); + } + else + { + if (item.TargetViewModelType.BaseType != typeof(BaseViewModel)) + { + throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); + } + + //Instantiate new view model + vm = (BaseViewModel)Activator.CreateInstance(item.TargetViewModelType); + _viewModels.Add(item.Id, vm); + } + //Activate viewmodel + vm.OnActive(); + + //Deactivate last viewModel + _lastViewModel.OnInactive(); + + //Assign viewModel + _lastViewModel = vm; + view.BindingContext = vm; + ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent"); viewContent.Content = view; @@ -47,7 +79,26 @@ namespace Aurora.Design.Views.Main { //Set initial view from first item in list ObservableCollection screenList = (ObservableCollection)MasterPage.ListView.ItemsSource; - var view = (View)Activator.CreateInstance(screenList.FirstOrDefault().FirstOrDefault().TargetType); + + //Assign viewModel + NavigationItem firstNavItem = screenList.FirstOrDefault().FirstOrDefault(); + var view = (View)Activator.CreateInstance(firstNavItem.TargetType); + + BaseViewModel vm = new BaseViewModel(); + if (_viewModels.ContainsKey(firstNavItem.Id)) + { + _viewModels.TryGetValue(firstNavItem.Id, out vm); + } + else + { + //Instantiate new view model + vm = (BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType); + _viewModels.Add(firstNavItem.Id, vm); + } + + view.BindingContext = vm; + _lastViewModel = vm; + vm.OnActive(); ContentPresenter viewContent = (ContentPresenter)ContentPage.Content.FindByName("ViewContent"); viewContent.Content = view; diff --git a/Aurora/Design/Views/MainView/MainViewModel.cs b/Aurora/Design/Views/MainView/MainViewModel.cs index ab57e18..8d9f1f0 100644 --- a/Aurora/Design/Views/MainView/MainViewModel.cs +++ b/Aurora/Design/Views/MainView/MainViewModel.cs @@ -32,12 +32,12 @@ namespace Aurora.Design.Views.MainView { _pages = new ObservableCollection(new[] { - new NavigationItem { Id = 4, Title = "Party", Group="Social", TargetType = typeof(PartyView)}, - new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ProfileView)}, - new NavigationItem { Id = 0, Title = "Songs", Group="Library", TargetType = typeof(SongsView) }, - new NavigationItem { Id = 1, Title = "Artists", Group="Library", TargetType = typeof(ArtistsView)}, - new NavigationItem { Id = 2, Title = "Albums", Group="Library", TargetType = typeof(AlbumsView)}, - new NavigationItem { Id = 3, Title = "Stations", Group="Library", TargetType = typeof(StationsView)}, + new NavigationItem { Id = 0, Title = "Songs", Group="Library", TargetType = typeof(SongsView), TargetViewModelType = typeof(SongsViewModel) }, + new NavigationItem { Id = 1, Title = "Artists", Group="Library", TargetType = typeof(ArtistsView), TargetViewModelType = typeof(ArtistsViewModel)}, + new NavigationItem { Id = 2, Title = "Albums", Group="Library", TargetType = typeof(AlbumsView), TargetViewModelType = typeof(AlbumsViewModel)}, + new NavigationItem { Id = 3, Title = "Stations", Group="Library", TargetType = typeof(StationsView), TargetViewModelType = typeof(StationsViewModel)}, + new NavigationItem { Id = 4, Title = "Party", Group="Social", TargetType = typeof(PartyView), TargetViewModelType = typeof(PartyViewModel)}, + new NavigationItem { Id = 5, Title = "Profile", Group="Social", TargetType = typeof(ProfileView), TargetViewModelType = typeof(ProfileViewModel)}, }); } diff --git a/Aurora/Design/Views/Party/PartyView.xaml.cs b/Aurora/Design/Views/Party/PartyView.xaml.cs index 4e044fe..d320265 100644 --- a/Aurora/Design/Views/Party/PartyView.xaml.cs +++ b/Aurora/Design/Views/Party/PartyView.xaml.cs @@ -8,7 +8,6 @@ namespace Aurora.Design.Views.Party public PartyView() { InitializeComponent(); - BindingContext = new PartyViewModel(); } } } diff --git a/Aurora/Design/Views/Profile/ProfileView.xaml.cs b/Aurora/Design/Views/Profile/ProfileView.xaml.cs index b4d8ba2..959dac9 100644 --- a/Aurora/Design/Views/Profile/ProfileView.xaml.cs +++ b/Aurora/Design/Views/Profile/ProfileView.xaml.cs @@ -9,7 +9,6 @@ namespace Aurora.Design.Views.Profile public ProfileView() { InitializeComponent(); - BindingContext = new ProfileViewModel(); } } } diff --git a/Aurora/Design/Views/Songs/SongsView.xaml b/Aurora/Design/Views/Songs/SongsView.xaml index 7f3a9a3..e0a29e0 100644 --- a/Aurora/Design/Views/Songs/SongsView.xaml +++ b/Aurora/Design/Views/Songs/SongsView.xaml @@ -5,10 +5,6 @@ xmlns:songs="clr-namespace:Aurora.Design.Views.Songs" xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid" x:Class="Aurora.Design.Views.Songs.SongsView"> - - -