daily pastebin goal
9%
SHARE
TWEET

Untitled

a guest Mar 18th, 2019 50 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using Xamarin.Forms;
  6. using ManageGo.Core.Services;
  7. using ManageGo.Core.ViewModels;
  8. using System.Reflection;
  9. using ManageGo.Core;
  10. using ManageGo.UI.Pages;
  11.  
  12. namespace ManageGo.UI.Navigation
  13. {
  14.     public interface IViewFor
  15.     {
  16.         object ViewModel { get; set; }
  17.     }
  18.  
  19.     public interface IViewFor<T> : IViewFor where T : BaseNavigationViewModel
  20.     {
  21.         new T ViewModel { get; set; }
  22.     }
  23.  
  24.     public class NavigationService : INavigationService
  25.     {
  26.         public static INavigationService Initialize(Assembly asm)
  27.         {
  28.             var navService = new NavigationService();
  29.             navService.RegisterViewModels(asm);
  30.  
  31.             ServiceContainer.Register<INavigationService>(() => navService);
  32.  
  33.             return navService;
  34.         }
  35.  
  36.         INavigation FormsNavigation
  37.         {
  38.             get
  39.             {
  40.                 var tabController = Application.Current.MainPage as TabbedPage;
  41.                 var masterController = Application.Current.MainPage as MasterDetailPage;
  42.  
  43.                 // First check to see if we're on a tabbed page, then master detail, finally go to overall fallback
  44.                 return tabController?.CurrentPage?.Navigation ??
  45.                                      (masterController?.Detail as TabbedPage)?.CurrentPage?.Navigation ?? // special consideration for a tabbed page inside master/detail
  46.                                      masterController?.Detail?.Navigation ??
  47.                                      Application.Current.MainPage.Navigation;
  48.             }
  49.         }
  50.  
  51.         // View model to view lookup - making the assumption that view model to view will always be 1:1
  52.         readonly Dictionary<Type, Type> _viewModelViewDictionary = new Dictionary<Type, Type>();
  53.  
  54.         #region Replace
  55.  
  56.         // Because we're going to do a hard switch of the page, either return
  57.         // the detail page, or if that's null, then the current main page      
  58.         Page DetailPage
  59.         {
  60.             get
  61.             {
  62.                 var masterController = Application.Current.MainPage as MasterDetailPage;
  63.                 return masterController?.Detail ?? Application.Current.MainPage;
  64.             }
  65.             set
  66.             {
  67.                 if (Application.Current.MainPage is MasterDetailPage masterController)
  68.                 {
  69.                     masterController.Detail = value;
  70.                     masterController.IsPresented = false;
  71.                 }
  72.                 else
  73.                 {
  74.                     Application.Current.MainPage = value;
  75.                 }
  76.             }
  77.         }
  78.        
  79.         public async Task SetDetailView(BaseNavigationViewModel viewModel, bool allowSamePageSet = false)
  80.         {
  81.         // Ensure that we're not pushing a new page if the DetailPage is already set to this type
  82.             if (!allowSamePageSet)
  83.             {
  84.                 IViewFor page;
  85.  
  86.                 if (DetailPage is NavigationPage)
  87.                     page = ((NavigationPage)DetailPage).RootPage as IViewFor;
  88.                 else
  89.                     page = DetailPage as IViewFor;
  90.  
  91.                 if (page?.ViewModel.GetType() == viewModel.GetType())
  92.                 {
  93.                     var masterController = Application.Current.MainPage as MasterDetailPage;
  94.  
  95.                     masterController.IsPresented = false;
  96.  
  97.                     return;
  98.                 }
  99.             }
  100.  
  101.         Page newDetailPage = await Task.Run(() =>
  102.         {
  103.             var view = InstantiateView(viewModel);
  104.  
  105.             // Tab pages shouldn't go into navigation pages
  106.             if (view is TabbedPage)
  107.                 newDetailPage = (Page)view;
  108.             else
  109.                 newDetailPage = new NavigationPage((Page)view);
  110.  
  111.             return newDetailPage;
  112.         });
  113.  
  114.             DetailPage = newDetailPage;
  115.         }
  116.              
  117.         public Task SetDetailView<T>(Action<T> initialize = null) where T : BaseNavigationViewModel
  118.     {
  119.         T viewModel = await Task.Run(() =>
  120.         {
  121.             // First instantiate the view model
  122.             viewModel = Activator.CreateInstance<T>();
  123.  
  124.             initialize?.Invoke(viewModel);
  125.  
  126.             return viewModel;
  127.         }).ConfigureAwait(false);
  128.  
  129.             // Actually switch the page
  130.             return SetDetailView(viewModel);
  131.         }
  132.  
  133.         public void SetRootView(BaseNavigationViewModel viewModel, bool withNavigationEnabled = true)
  134.         {
  135.             if (InstantiateView(viewModel) is Page view)
  136.             {
  137.                 if (withNavigationEnabled)
  138.                     Application.Current.MainPage = new NavigationPage(view);
  139.                 else
  140.                     Application.Current.MainPage = view;
  141.             }
  142.         }
  143.  
  144.         #endregion
  145.  
  146.         #region Registration
  147.  
  148.         public void RegisterViewModels(Assembly asm)
  149.         {
  150.             // Loop through everything in the assembly that implements IViewFor<T>
  151.             foreach (var type in asm.DefinedTypes.Where(dt => !dt.IsAbstract &&
  152.                 dt.ImplementedInterfaces.Any(ii => ii == typeof(IViewFor))))
  153.             {
  154.                 // Get the IViewFor<T> portion of the type that implements it
  155.                 var viewForType = type.ImplementedInterfaces.FirstOrDefault(
  156.                     ii => ii.IsConstructedGenericType &&
  157.                     ii.GetGenericTypeDefinition() == typeof(IViewFor<>));
  158.  
  159.                 // Register it, using the T as the key and the view as the value
  160.                 Register(viewForType.GenericTypeArguments[0], type.AsType());
  161.             }
  162.         }
  163.  
  164.         public void Register(Type viewModelType, Type viewType)
  165.         {
  166.             if (!_viewModelViewDictionary.ContainsKey(viewModelType))
  167.                 _viewModelViewDictionary.Add(viewModelType, viewType);
  168.         }
  169.  
  170.         #endregion
  171.  
  172.         #region Pop
  173.  
  174.         public Task PopAsync() => FormsNavigation.PopAsync(true);
  175.  
  176.         public Task PopModalAsync() => FormsNavigation.PopModalAsync(true);
  177.  
  178.     public Task PopPopupAsync(bool animate = true) => FormsNavigation.PopPopupAsync(animate);
  179.  
  180.         public Task PopToRootAsync(bool animate) => FormsNavigation.PopToRootAsync(animate);
  181.  
  182.         #endregion
  183.  
  184.         #region Push
  185.  
  186.         public Task PushAsync(BaseNavigationViewModel viewModel)
  187.         {
  188.             var view = InstantiateView(viewModel);
  189.             return FormsNavigation.PushAsync((Page)view);
  190.         }
  191.  
  192.         public Task PushModalAsync(BaseNavigationViewModel viewModel)
  193.         {
  194.             viewModel.Type = Core.Enumerations.ViewModelType.Modal;
  195.  
  196.             var view = InstantiateView(viewModel);
  197.  
  198.             // Most likely we're going to want to put this into a navigation page so we can have a title bar on it
  199.             var nv = new NavigationPage((Page)view);
  200.  
  201.             return FormsNavigation.PushModalAsync(nv);
  202.         }
  203.  
  204.     public Task PushPopupAsync(BaseNavigationViewModel viewModel, bool animate = true)
  205.         {
  206.         viewModel.Type = Core.Enumerations.ViewModelType.Popup;
  207.  
  208.         var view = InstantiateView(viewModel);
  209.  
  210.         return FormsNavigation.PushPopupAsync((PopupPage)view);
  211.         }
  212.  
  213.         public Task PushAsync<T>(Action<T> initialize = null) where T : BaseNavigationViewModel
  214.         {
  215.             T viewModel;
  216.            
  217.             // Instantiate the view model & invoke the initialize method, if any
  218.             viewModel = Activator.CreateInstance<T>();
  219.        
  220.             initialize?.Invoke(viewModel);
  221.  
  222.             return PushAsync(viewModel);
  223.         }
  224.  
  225.         public Task PushModalAsync<T>(Action<T> initialize = null) where T : BaseNavigationViewModel
  226.         {
  227.             T viewModel;
  228.  
  229.             // Instantiate the view model & invoke the initialize method, if any
  230.             viewModel = Activator.CreateInstance<T>();
  231.  
  232.         viewModel.Type = Core.Enumerations.ViewModelType.Modal;
  233.  
  234.             initialize?.Invoke(viewModel);
  235.  
  236.             return PushModalAsync(viewModel);
  237.         }
  238.  
  239.         #endregion
  240.  
  241.         IViewFor InstantiateView(BaseNavigationViewModel viewModel)
  242.         {
  243.             // Figure out what type the view model is
  244.             var viewModelType = viewModel.GetType();
  245.  
  246.             // look up what type of view it corresponds to
  247.             var viewType = _viewModelViewDictionary[viewModelType];
  248.  
  249.             // instantiate it
  250.             var view = (IViewFor)Activator.CreateInstance(viewType);
  251.  
  252.             view.ViewModel = viewModel;
  253.  
  254.             return view;
  255.         }
  256.     }
  257. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top