diff --git a/Borepin/Borepin/App.xaml.cs b/Borepin/Borepin/App.xaml.cs index cf0276d..8c84b7d 100644 --- a/Borepin/Borepin/App.xaml.cs +++ b/Borepin/Borepin/App.xaml.cs @@ -18,7 +18,7 @@ namespace Borepin Task InitNavigation() { var navService = PageModelLocator.Resolve(); - return navService.NaviagteToAsync(); + return navService.NaviagteToAsync(null, true); } protected override async void OnStart() diff --git a/Borepin/Borepin/Base/PageModelLocator.cs b/Borepin/Borepin/Base/PageModelLocator.cs index 8f2963b..9a1f5dc 100644 --- a/Borepin/Borepin/Base/PageModelLocator.cs +++ b/Borepin/Borepin/Base/PageModelLocator.cs @@ -18,9 +18,15 @@ namespace Borepin.Base _ViewLookUp = new Dictionary(); // Register Pages and PageModels + Register(); + Register(); + + Register(); + Register(); + Register(); Register(); - + // Register Services (Services are registered by Singeltons default) _Container.Register(); } diff --git a/Borepin/Borepin/Behaviour/Base/BehaviorBase.cs b/Borepin/Borepin/Behaviour/Base/BehaviorBase.cs new file mode 100644 index 0000000..807a4f2 --- /dev/null +++ b/Borepin/Borepin/Behaviour/Base/BehaviorBase.cs @@ -0,0 +1,37 @@ +using System; +using Xamarin.Forms; + +namespace Borepin.Behaviour.Base +{ + public class BehaviorBase : Behavior where T : BindableObject + { + public T AssociatedObject { get; private set; } + protected override void OnAttachedTo(T bindable) + { + base.OnAttachedTo(bindable); + AssociatedObject = bindable; + + if (bindable.BindingContext != null) + BindingContext = bindable.BindingContext; + + bindable.BindingContextChanged += OnBindingContextChanged; + } + protected override void OnDetachingFrom(T bindable) + { + base.OnDetachingFrom(bindable); + bindable.BindingContextChanged -= OnBindingContextChanged; + AssociatedObject = null; + } + + void OnBindingContextChanged(object sender, EventArgs e) + { + OnBindingContextChanged(); + } + + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + BindingContext = AssociatedObject.BindingContext; + } + } +} diff --git a/Borepin/Borepin/Behaviour/EventToCommandBehavior.cs b/Borepin/Borepin/Behaviour/EventToCommandBehavior.cs new file mode 100644 index 0000000..65441a2 --- /dev/null +++ b/Borepin/Borepin/Behaviour/EventToCommandBehavior.cs @@ -0,0 +1,91 @@ +using Borepin.Behaviour.Base; +using System; +using System.Reflection; +using System.Windows.Input; +using Xamarin.Forms; + +namespace Borepin.Behaviour +{ + public class EventToCommandBehavior : BehaviorBase + { + Delegate eventHandler; + public static readonly BindableProperty EventNameProperty = BindableProperty.Create("EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged); + public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(EventToCommandBehavior), null); + + public string EventName + { + get { return (string)GetValue(EventNameProperty); } + set { SetValue(EventNameProperty, value); } + } + public ICommand Command + { + get { return (ICommand)GetValue(CommandProperty); } + set { SetValue(CommandProperty, value); } + } + + protected override void OnAttachedTo(VisualElement bindable) + { + base.OnAttachedTo(bindable); + RegisterEvent(EventName); + } + + protected override void OnDetachingFrom(VisualElement bindable) + { + DeregisterEvent(EventName); + base.OnDetachingFrom(bindable); + } + static void OnEventNameChanged(BindableObject bindable, object oldValue, object newValue) + { + var behavior = (EventToCommandBehavior)bindable; + + if (behavior.AssociatedObject == null) return; + + string oldEventName = (string)oldValue; + string newEventName = (string)newValue; + + behavior.DeregisterEvent(oldEventName); + behavior.RegisterEvent(newEventName); + } + + void RegisterEvent(string name) + { + if (string.IsNullOrWhiteSpace(name)) return; + + EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name); + + if (eventInfo == null) + throw new ArgumentException(string.Format("EventToCommandBehavior: Can't register the '{0}' event.", EventName)); + + MethodInfo methodInfo = typeof(EventToCommandBehavior).GetTypeInfo().GetDeclaredMethod("OnEvent"); + eventHandler = methodInfo.CreateDelegate(eventInfo.EventHandlerType, this); + eventInfo.AddEventHandler(AssociatedObject, eventHandler); + } + + void DeregisterEvent(string name) + { + if (string.IsNullOrWhiteSpace(name) || eventHandler == null) + return; + + EventInfo eventInfo = AssociatedObject.GetType().GetRuntimeEvent(name); + + if (eventInfo == null) + throw new ArgumentException(string.Format("EventToCommandBehavior: Can't de-register the '{0}' event.", EventName)); + + eventInfo.RemoveEventHandler(AssociatedObject, eventHandler); + eventHandler = null; + } + + void OnEvent(object sender, object eventArgs) + { + if (Command == null) return; + + object resolvedParameter; + + resolvedParameter = eventArgs; + + if (Command.CanExecute(resolvedParameter)) + Command.Execute(resolvedParameter); + } + + } +} diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 1bda1c9..4cdc56d 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -24,6 +24,15 @@ + + BorpinMasterDetailPage.xaml + + + BorpinMasterPage.xaml + + + MachinesPage.xaml + True True @@ -39,12 +48,24 @@ + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + + + MSBuild:UpdateDesignTimeXaml + MSBuild:UpdateDesignTimeXaml MSBuild:UpdateDesignTimeXaml + + MSBuild:UpdateDesignTimeXaml + ResXFileCodeGenerator Resources.Designer.cs diff --git a/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml b/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml new file mode 100644 index 0000000..013e144 --- /dev/null +++ b/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml.cs b/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml.cs new file mode 100644 index 0000000..bdcd427 --- /dev/null +++ b/Borepin/Borepin/Page/BorpinMasterDetailPage.xaml.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace Borepin.Page +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class BorpinMasterDetailPage : MasterDetailPage + { + public BorpinMasterDetailPage() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/Page/BorpinMasterPage.xaml b/Borepin/Borepin/Page/BorpinMasterPage.xaml new file mode 100644 index 0000000..2547888 --- /dev/null +++ b/Borepin/Borepin/Page/BorpinMasterPage.xaml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Borepin/Borepin/Page/BorpinMasterPage.xaml.cs b/Borepin/Borepin/Page/BorpinMasterPage.xaml.cs new file mode 100644 index 0000000..e88b29d --- /dev/null +++ b/Borepin/Borepin/Page/BorpinMasterPage.xaml.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace Borepin.Page +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class BorpinMasterPage : ContentPage + { + public BorpinMasterPage() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/Page/MachinesPage.xaml b/Borepin/Borepin/Page/MachinesPage.xaml new file mode 100644 index 0000000..2aaf35a --- /dev/null +++ b/Borepin/Borepin/Page/MachinesPage.xaml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/Borepin/Borepin/Page/MachinesPage.xaml.cs b/Borepin/Borepin/Page/MachinesPage.xaml.cs new file mode 100644 index 0000000..83d1f70 --- /dev/null +++ b/Borepin/Borepin/Page/MachinesPage.xaml.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace Borepin.Page +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class MachinesPage : ContentPage + { + public MachinesPage() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/Page/MasterMenuItem.cs b/Borepin/Borepin/Page/MasterMenuItem.cs new file mode 100644 index 0000000..8551311 --- /dev/null +++ b/Borepin/Borepin/Page/MasterMenuItem.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Borepin.Page +{ + + public class MasterMenuItem + { + public MasterMenuItem() + { + TargetType = typeof(MasterMenuItem); + } + public int Id { get; set; } + public string Title { get; set; } + + public Type TargetType { get; set; } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/Page/SettingsPage.xaml b/Borepin/Borepin/Page/SettingsPage.xaml new file mode 100644 index 0000000..554a3db --- /dev/null +++ b/Borepin/Borepin/Page/SettingsPage.xaml @@ -0,0 +1,11 @@ + + + + + + + \ No newline at end of file diff --git a/Borepin/Borepin/Page/SettingsPage.xaml.cs b/Borepin/Borepin/Page/SettingsPage.xaml.cs new file mode 100644 index 0000000..93d965a --- /dev/null +++ b/Borepin/Borepin/Page/SettingsPage.xaml.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace Borepin.Page +{ + [XamlCompilation(XamlCompilationOptions.Compile)] + public partial class SettingsPage : ContentPage + { + public SettingsPage() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Borepin/Borepin/PageModel/BorpinMasterDetailPageModel.cs b/Borepin/Borepin/PageModel/BorpinMasterDetailPageModel.cs new file mode 100644 index 0000000..423f368 --- /dev/null +++ b/Borepin/Borepin/PageModel/BorpinMasterDetailPageModel.cs @@ -0,0 +1,48 @@ +using Borepin.Base; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Borepin.PageModel +{ + public class BorpinMasterDetailPageModel : PageModelBase + { + public BorpinMasterDetailPageModel(BorpinMasterPageModel borpinMasterPM, MachinesPageModel machinesPM, SettingsPageModel settingsPM) + { + BorpinMasterPM = borpinMasterPM; + MachinesPM = machinesPM; + SettingsPM = settingsPM; + } + + private BorpinMasterPageModel _BorpinMasterPM; + public BorpinMasterPageModel BorpinMasterPM + { + get => _BorpinMasterPM; + set => SetProperty(ref _BorpinMasterPM, value); + } + + private MachinesPageModel _MachinesPM; + public MachinesPageModel MachinesPM + { + get => _MachinesPM; + set => SetProperty(ref _MachinesPM, value); + } + + private SettingsPageModel _SettingsPM; + public SettingsPageModel SettingsPM + { + get => _SettingsPM; + set => SetProperty(ref _SettingsPM, value); + } + + public override Task InitializeAsync(object navigationData) + { + return Task.WhenAny( + base.InitializeAsync(navigationData), + BorpinMasterPM.InitializeAsync(null), + MachinesPM.InitializeAsync(null), + SettingsPM.InitializeAsync(null)); + } + } +} diff --git a/Borepin/Borepin/PageModel/BorpinMasterPageModel.cs b/Borepin/Borepin/PageModel/BorpinMasterPageModel.cs new file mode 100644 index 0000000..1925876 --- /dev/null +++ b/Borepin/Borepin/PageModel/BorpinMasterPageModel.cs @@ -0,0 +1,76 @@ +using Borepin.Base; +using Borepin.Page; +using Borepin.Service.Navigation; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using System.Xml.Schema; +using Xamarin.Forms; + +namespace Borepin.PageModel +{ + public class BorpinMasterPageModel : PageModelBase + { + private INavigationService _NavigationService; + + public BorpinMasterPageModel(INavigationService navigationService) + { + _NavigationService = navigationService; + MasterMenu = new ObservableCollection() + { + new MasterMenuItem{ Id = 0, Title = "Machines" }, + new MasterMenuItem{ Id = 1, Title = "Settings" } + }; + + _showDetailPageAsyncCommand = new Command(ShowDetailPageAsync); + } + + private ObservableCollection _MasterMenu; + public ObservableCollection MasterMenu + { + get => _MasterMenu; + set => SetProperty(ref _MasterMenu, value); + } + + private MasterMenuItem _MasterMenu_ItemSelected; + public MasterMenuItem MasterMenu_ItemSelected + { + get => _MasterMenu_ItemSelected; + set => SetProperty(ref _MasterMenu_ItemSelected, value); + } + + private ICommand _showDetailPageAsyncCommand; + public ICommand ShowDetailPageAsyncCommand + { + get => _showDetailPageAsyncCommand; + set => SetProperty(ref _showDetailPageAsyncCommand, value); + } + private async void ShowDetailPageAsync() + { + switch (MasterMenu_ItemSelected.Title) + { + case "Machines": + await _NavigationService.NaviagteToAsync(); + break; + case "Settings": + await _NavigationService.NaviagteToAsync(); + break; + default: + break; + } + + if (Application.Current.MainPage is MasterDetailPage masterDetailPage) + { + masterDetailPage.IsPresented = false; + } + else if (Application.Current.MainPage is NavigationPage navigationPage + && navigationPage.CurrentPage is MasterDetailPage nestedMasterDetail) + { + nestedMasterDetail.IsPresented = false; + } + } + } +} diff --git a/Borepin/Borepin/PageModel/MachinesPageModel.cs b/Borepin/Borepin/PageModel/MachinesPageModel.cs new file mode 100644 index 0000000..23cd7f6 --- /dev/null +++ b/Borepin/Borepin/PageModel/MachinesPageModel.cs @@ -0,0 +1,20 @@ +using Borepin.Base; +using Borepin.Service.Navigation; +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Input; +using Xamarin.Forms; + +namespace Borepin.PageModel +{ + public class MachinesPageModel : PageModelBase + { + private INavigationService _NaviagtionService; + + public MachinesPageModel(INavigationService navigationService) + { + _NaviagtionService = navigationService; + } + } +} diff --git a/Borepin/Borepin/PageModel/SettingsPageModel.cs b/Borepin/Borepin/PageModel/SettingsPageModel.cs new file mode 100644 index 0000000..3f4c29d --- /dev/null +++ b/Borepin/Borepin/PageModel/SettingsPageModel.cs @@ -0,0 +1,12 @@ +using Borepin.Base; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Borepin.PageModel +{ + public class SettingsPageModel : PageModelBase + { + + } +} diff --git a/Borepin/Borepin/Service/Navigation/NavigationService.cs b/Borepin/Borepin/Service/Navigation/NavigationService.cs index 36f0b6a..eb27bea 100644 --- a/Borepin/Borepin/Service/Navigation/NavigationService.cs +++ b/Borepin/Borepin/Service/Navigation/NavigationService.cs @@ -20,11 +20,27 @@ namespace Borepin.Service.Navigation Xamarin.Forms.Page page = PageModelLocator.CreatePage(typeof(TPageModelBase)); if(setRoot) { - App.Current.MainPage = new NavigationPage(page); + if (page is TabbedPage tabbedPage) + { + App.Current.MainPage = tabbedPage; + } + else if(page is MasterDetailPage masterDetailPage) + { + App.Current.MainPage = masterDetailPage; + } + else + { + App.Current.MainPage = new NavigationPage(page); + } } else { - if(App.Current.MainPage is NavigationPage navPage) + if (App.Current.MainPage is MasterDetailPage masterDetailPage) + { + masterDetailPage.Detail = new NavigationPage(page); + } + + if (App.Current.MainPage is NavigationPage navPage) { await navPage.PushAsync(page); }