Advertisement
Guest User

Untitled

a guest
Mar 18th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.17 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement