Instantly share code, notes, and snippets.
Last active
July 29, 2018 23:34
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save jlucaspains/e799b2b019e654b2a59e01474928152a to your computer and use it in GitHub Desktop.
FreshMVVM alternative MasterDetailNavigationContainer with lazy loaded pages and FontAwesome icons
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using FreshMvvm; | |
using lpains.Views; | |
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Xamarin.Forms; | |
namespace lpains.Helpers | |
{ | |
public class Grouping<K, T> : List<T> | |
{ | |
public K Key { get; private set; } | |
public Grouping(K key, List<T> items) | |
{ | |
Key = key; | |
foreach (var item in items) | |
this.Add(item); | |
} | |
} | |
public class MasterDetailNavigationContainer : Xamarin.Forms.MasterDetailPage, IFreshNavigationService | |
{ | |
private MasterView _masterView; | |
private ListView _listView; | |
public ObservableCollection<LazyLoadedPage> Pages { get; } = new ObservableCollection<LazyLoadedPage>(); | |
public MasterDetailNavigationContainer() : this(Constants.DefaultNavigationServiceName) | |
{ | |
} | |
public MasterDetailNavigationContainer(string navigationServiceName) | |
{ | |
NavigationServiceName = navigationServiceName; | |
} | |
public void Init(string menuTitle, string menuIcon = null) | |
{ | |
CreateMenuPage(menuTitle, menuIcon); | |
CreateDetailPage(); | |
RegisterNavigation(); | |
} | |
protected virtual void RegisterNavigation() | |
{ | |
FreshIOC.Container.Register<IFreshNavigationService>(this, NavigationServiceName); | |
} | |
public virtual void AddPage<T>(string title, string group, string icon = null, object data = null) where T : FreshBasePageModel | |
{ | |
var pageToAdd = new LazyLoadedPage { ViewModelType = typeof(T), Data = data, Title = title, Icon = icon, Group = group }; | |
Pages.Add(pageToAdd); | |
if (Pages.Count == 1) | |
Detail = ResolvePage(pageToAdd); | |
_listView.ItemsSource = Pages.GroupBy(item => item.Group).Select(item => new Grouping<string, LazyLoadedPage>(item.Key, item.ToList())).ToList(); | |
} | |
public virtual void AddPage(string modelName, string title, string icon = null, object data = null) | |
{ | |
var pageToAdd = new LazyLoadedPage { ViewModelType = Type.GetType(modelName), Data = data, Title = title, Icon = icon }; | |
Pages.Add(pageToAdd); | |
if (Pages.Count == 1) | |
Detail = ResolvePage(pageToAdd); | |
} | |
internal Page CreateContainerPageSafe(Page page) | |
{ | |
if (page is NavigationPage || page is MasterDetailPage || page is TabbedPage) | |
return page; | |
return CreateContainerPage(page); | |
} | |
protected virtual Page CreateContainerPage(Page page) | |
{ | |
return new NavigationPage(page); | |
} | |
protected virtual void CreateMenuPage(string menuPageTitle, string menuIcon = null) | |
{ | |
_masterView = new MasterView(); | |
_listView = _masterView.FindByName<ListView>("ListView"); | |
var source = Pages.GroupBy(item => item.Group).Select(item => new Grouping<string, LazyLoadedPage>(item.Key, item.ToList())).ToList(); | |
_listView.ItemTapped += (sender, args) => | |
{ | |
var lazyLoadedPage = (LazyLoadedPage)args.Item; | |
if (Pages.Contains(lazyLoadedPage)) | |
{ | |
var page = lazyLoadedPage.Page; | |
if (page == null) | |
page = ResolvePage(lazyLoadedPage); | |
Detail = page; | |
} | |
IsPresented = false; | |
}; | |
//menuPage.Content = _listView; | |
var navPage = new NavigationPage(_masterView) { Title = menuPageTitle }; //adding an actual icon does't seem to work. The unicode here is a temporarily solution | |
if (!string.IsNullOrEmpty(menuIcon)) | |
{ | |
navPage.Icon = menuIcon; | |
Icon = menuIcon; | |
} | |
Master = navPage; | |
} | |
protected virtual void CreateDetailPage() | |
{ | |
Detail = CreateContainerPage(new Page()); | |
} | |
protected virtual Page ResolvePage(LazyLoadedPage lazyLoadedPage) | |
{ | |
var innerPage = FreshPageModelResolver.ResolvePageModel(lazyLoadedPage.ViewModelType, lazyLoadedPage.Data); | |
innerPage.GetModel().CurrentNavigationServiceName = NavigationServiceName; | |
return CreateContainerPage(innerPage); | |
} | |
public Task PushPage(Page page, FreshBasePageModel model, bool modal = false, bool animate = true) | |
{ | |
if (modal) | |
return Navigation.PushModalAsync(CreateContainerPageSafe(page)); | |
return (Detail as NavigationPage).PushAsync(page, animate); //TODO: make this better | |
} | |
public Task PopPage(bool modal = false, bool animate = true) | |
{ | |
if (modal) | |
return Navigation.PopModalAsync(animate); | |
return (Detail as NavigationPage).PopAsync(animate); //TODO: make this better | |
} | |
public Task PopToRoot(bool animate = true) | |
{ | |
return (Detail as NavigationPage).PopToRootAsync(animate); | |
} | |
public string NavigationServiceName { get; private set; } | |
public void NotifyChildrenPageWasPopped() | |
{ | |
if (Master is NavigationPage masterNavPage) | |
masterNavPage.NotifyAllChildrenPopped(); | |
if (Master is IFreshNavigationService masterFreshNavPage) | |
masterFreshNavPage.NotifyChildrenPageWasPopped(); | |
foreach (var page in this.Pages) | |
{ | |
if (page.Page is NavigationPage navPage) | |
navPage.NotifyAllChildrenPopped(); | |
if (page.Page is IFreshNavigationService freshNavPage) | |
freshNavPage.NotifyChildrenPageWasPopped(); | |
} | |
if (Pages != null && !Pages.Any(item => item.Page == Detail) && Detail is NavigationPage) | |
((NavigationPage)Detail).NotifyAllChildrenPopped(); | |
if (Pages != null && !Pages.Any(item => item.Page == Detail) && Detail is IFreshNavigationService) | |
((IFreshNavigationService)Detail).NotifyChildrenPageWasPopped(); | |
} | |
public Task<FreshBasePageModel> SwitchSelectedRootPageModel<T>() where T : FreshBasePageModel | |
{ | |
var lazyLoadedPage = Pages.FirstOrDefault(o => o.Page.GetModel().GetType().FullName == typeof(T).FullName); | |
var page = lazyLoadedPage.Page; | |
if (page == null) | |
page = ResolvePage(lazyLoadedPage); | |
_listView.SelectedItem = page; | |
return Task.FromResult((Detail as NavigationPage).CurrentPage.GetModel()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment