diff --git a/src/FreshMvvm/FreshAwaitCommand.cs b/src/FreshMvvm/FreshAwaitCommand.cs index 75b9a2f..204893a 100644 --- a/src/FreshMvvm/FreshAwaitCommand.cs +++ b/src/FreshMvvm/FreshAwaitCommand.cs @@ -1,9 +1,67 @@ using System; +using System.Reflection; using System.Threading.Tasks; using System.Windows.Input; namespace FreshMvvm { + public sealed class FreshAwaitCommand : FreshAwaitCommand + { + public FreshAwaitCommand(Action> execute) + : base((o, tcs) => + { + if (IsValidParameter(o)) + { + execute((T)o, tcs); + } + }) + { + if (execute == null) + { + throw new ArgumentNullException(nameof(execute)); + } + } + + public FreshAwaitCommand(Action> execute, Func canExecute) + : base((o, tcs) => + { + if (IsValidParameter(o)) + { + execute((T)o, tcs); + } + }, o => IsValidParameter(o) && canExecute((T)o)) + { + if (execute == null) + { + throw new ArgumentNullException(nameof(execute)); + } + if (canExecute == null) + { + throw new ArgumentNullException(nameof(canExecute)); + } + } + + private static bool IsValidParameter(object o) + { + if (o != null) + { + // The parameter isn't null, so we don't have to worry whether null is a valid option + return o is T; + } + + var t = typeof(T); + + // The parameter is null. Is T Nullable? + if (Nullable.GetUnderlyingType(t) != null) + { + return true; + } + + // Not a Nullable, if it's a value type then null is not valid + return !t.GetTypeInfo().IsValueType; + } + } + /// /// FreshAwaitCommand is designed to avoid the double tap issue in Xamarin.Forms for Android, /// in Xamarin.Forms it's a common issue that double taps on command would open the same window multiple times. diff --git a/src/FreshMvvm/NavigationContainers/FreshMasterDetailNavigationContainer.cs b/src/FreshMvvm/NavigationContainers/FreshMasterDetailNavigationContainer.cs index ea24df1..f025f45 100644 --- a/src/FreshMvvm/NavigationContainers/FreshMasterDetailNavigationContainer.cs +++ b/src/FreshMvvm/NavigationContainers/FreshMasterDetailNavigationContainer.cs @@ -1,69 +1,66 @@ using System; -using System.Threading.Tasks; -using Xamarin.Forms; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Linq; +using System.Threading.Tasks; +using Xamarin.Forms; namespace FreshMvvm { public class FreshMasterDetailNavigationContainer : Xamarin.Forms.MasterDetailPage, IFreshNavigationService { - List _pagesInner = new List (); - Dictionary _pages = new Dictionary (); - ContentPage _menuPage; - ObservableCollection _pageNames = new ObservableCollection (); - ListView _listView = new ListView (); + private ListView _listView = new ListView(); + + protected List PagesInner = new List(); + protected ObservableCollection PageNames = new ObservableCollection(); - public Dictionary Pages { get { return _pages; } } - protected ObservableCollection PageNames { get { return _pageNames; } } + public Dictionary Pages = new Dictionary(); - public FreshMasterDetailNavigationContainer () : this(Constants.DefaultNavigationServiceName) - { + public FreshMasterDetailNavigationContainer() : this(Constants.DefaultNavigationServiceName) + { } - public FreshMasterDetailNavigationContainer (string navigationServiceName) - { - NavigationServiceName = navigationServiceName; - RegisterNavigation (); + public FreshMasterDetailNavigationContainer(string navigationServiceName) + { + NavigationServiceName = navigationServiceName; + RegisterNavigation(); } - public void Init (string menuTitle, string menuIcon = null) + public void Init(string menuTitle, string menuIcon = null) { - CreateMenuPage (menuTitle, menuIcon); - RegisterNavigation (); + CreateMenuPage(menuTitle, menuIcon); + RegisterNavigation(); } - protected virtual void RegisterNavigation () + protected virtual void RegisterNavigation() { - FreshIOC.Container.Register (this, NavigationServiceName); + FreshIOC.Container.Register(this, NavigationServiceName); } - public virtual void AddPage (string title, object data = null) where T : FreshBasePageModel + public virtual void AddPage(string title, object data = null) where T : FreshBasePageModel { - var page = FreshPageModelResolver.ResolvePageModel (data); - page.GetModel ().CurrentNavigationServiceName = NavigationServiceName; - _pagesInner.Add(page); - var navigationContainer = CreateContainerPage (page); - _pages.Add (title, navigationContainer); - _pageNames.Add (title); - if (_pages.Count == 1) + var page = FreshPageModelResolver.ResolvePageModel(data); + page.GetModel().CurrentNavigationServiceName = NavigationServiceName; + PagesInner.Add(page); + var navigationContainer = CreateContainerPage(page); + Pages.Add(title, navigationContainer); + PageNames.Add(title); + if (Pages.Count == 1) Detail = navigationContainer; } - public virtual void AddPage(string modelName, string title, object data = null) + + public virtual void AddPage(Type pageModel, string title, object data = null) { - var pageModelType = Type.GetType(modelName); - var page = FreshPageModelResolver.ResolvePageModel(pageModelType, null); + var page = FreshPageModelResolver.ResolvePageModel(pageModel, data); page.GetModel().CurrentNavigationServiceName = NavigationServiceName; - _pagesInner.Add(page); + PagesInner.Add(page); var navigationContainer = CreateContainerPage(page); - _pages.Add(title, navigationContainer); - _pageNames.Add(title); - if (_pages.Count == 1) + Pages.Add(title, navigationContainer); + PageNames.Add(title); + if (Pages.Count == 1) Detail = navigationContainer; } - internal Page CreateContainerPageSafe (Page page) + internal Page CreateContainerPageSafe(Page page) { if (page is NavigationPage || page is MasterDetailPage || page is TabbedPage) return page; @@ -71,21 +68,23 @@ internal Page CreateContainerPageSafe (Page page) return CreateContainerPage(page); } - protected virtual Page CreateContainerPage (Page page) + protected virtual Page CreateContainerPage(Page page) { - return new NavigationPage (page); + return new NavigationPage(page); } - protected virtual void CreateMenuPage (string menuPageTitle, string menuIcon = null) + protected virtual void CreateMenuPage(string menuPageTitle, string menuIcon = null) { - _menuPage = new ContentPage (); - _menuPage.Title = menuPageTitle; - - _listView.ItemsSource = _pageNames; - - _listView.ItemSelected += (sender, args) => { - if (_pages.ContainsKey ((string)args.SelectedItem)) { - Detail = _pages [(string)args.SelectedItem]; + var _menuPage = new ContentPage(); + _menuPage.Title = menuPageTitle; + + _listView.ItemsSource = PageNames; + + _listView.ItemSelected += (sender, args) => + { + if (Pages.ContainsKey((string)args.SelectedItem)) + { + Detail = Pages[(string)args.SelectedItem]; } IsPresented = false; @@ -93,31 +92,31 @@ protected virtual void CreateMenuPage (string menuPageTitle, string menuIcon = n _menuPage.Content = _listView; - var navPage = new NavigationPage (_menuPage) { Title = "Menu" }; + var navPage = new NavigationPage(_menuPage) { Title = "Menu" }; - if (!string.IsNullOrEmpty (menuIcon)) + if (!string.IsNullOrEmpty(menuIcon)) navPage.Icon = menuIcon; - + Master = navPage; } - public Task PushPage (Page page, FreshBasePageModel model, bool modal = false, bool animate = true) + 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 - } + 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) - { + 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 - } + return Navigation.PopModalAsync(animate); + return (Detail as NavigationPage).PopAsync(animate); //TODO: make this better + } - public Task PopToRoot (bool animate = true) + public Task PopToRoot(bool animate = true) { - return (Detail as NavigationPage).PopToRootAsync (animate); + return (Detail as NavigationPage).PopToRootAsync(animate); } public string NavigationServiceName { get; private set; } @@ -128,7 +127,7 @@ public void NotifyChildrenPageWasPopped() ((NavigationPage)Master).NotifyAllChildrenPopped(); if (Master is IFreshNavigationService) ((IFreshNavigationService)Master).NotifyChildrenPageWasPopped(); - + foreach (var page in this.Pages.Values) { if (page is NavigationPage) @@ -144,12 +143,11 @@ public void NotifyChildrenPageWasPopped() public Task SwitchSelectedRootPageModel() where T : FreshBasePageModel { - var tabIndex = _pagesInner.FindIndex(o => o.GetModel().GetType().FullName == typeof(T).FullName); + var tabIndex = PagesInner.FindIndex(o => o.GetModel().GetType().FullName == typeof(T).FullName); - _listView.SelectedItem = _pageNames[tabIndex]; + _listView.SelectedItem = PageNames[tabIndex]; return Task.FromResult((Detail as NavigationPage).CurrentPage.GetModel()); } } -} - +} \ No newline at end of file