diff --git a/src/Cimbalino.Toolkit (UWP)/Cimbalino.Toolkit (UWP).csproj b/src/Cimbalino.Toolkit (UWP)/Cimbalino.Toolkit (UWP).csproj index b9b1836..8a52d66 100644 --- a/src/Cimbalino.Toolkit (UWP)/Cimbalino.Toolkit (UWP).csproj +++ b/src/Cimbalino.Toolkit (UWP)/Cimbalino.Toolkit (UWP).csproj @@ -166,6 +166,9 @@ Controls\ExtendedPageBase.cs + + Controls\IMasterDetailFrame.cs + Converters\BooleanToBrushConverter.cs diff --git a/src/Cimbalino.Toolkit (WP8)/Cimbalino.Toolkit (WP8).csproj b/src/Cimbalino.Toolkit (WP8)/Cimbalino.Toolkit (WP8).csproj index 9172d3b..969edd7 100644 --- a/src/Cimbalino.Toolkit (WP8)/Cimbalino.Toolkit (WP8).csproj +++ b/src/Cimbalino.Toolkit (WP8)/Cimbalino.Toolkit (WP8).csproj @@ -113,6 +113,7 @@ + diff --git a/src/Cimbalino.Toolkit (WP8)/Controls/IMasterDetailFrame.cs b/src/Cimbalino.Toolkit (WP8)/Controls/IMasterDetailFrame.cs new file mode 100644 index 0000000..97a94b8 --- /dev/null +++ b/src/Cimbalino.Toolkit (WP8)/Controls/IMasterDetailFrame.cs @@ -0,0 +1,28 @@ +// **************************************************************************** +// +// Copyright © Pedro Lamas 2014 +// +// **************************************************************************** +// Pedro Lamas +// pedrolamas@gmail.com +// Cimbalino.Toolkit +// http://www.pedrolamas.com +// +// See license.txt in this solution or http://www.pedrolamas.com/license_MIT.txt +// +// **************************************************************************** + +namespace Cimbalino.Toolkit.Controls +{ + /// + /// Represents the basic operations for the MasterDetail control. + /// + public interface IMasterDetailFrame + { + /// + /// Called when the user presses the hardware back button. + /// + /// true if the back button press has been handled; otherwise, false. + bool HandleBackKeyPress(); + } +} \ No newline at end of file diff --git a/src/Cimbalino.Toolkit (WP8)/Services/NavigationService.cs b/src/Cimbalino.Toolkit (WP8)/Services/NavigationService.cs index fec20c3..d093bea 100644 --- a/src/Cimbalino.Toolkit (WP8)/Services/NavigationService.cs +++ b/src/Cimbalino.Toolkit (WP8)/Services/NavigationService.cs @@ -143,6 +143,48 @@ public virtual bool Navigate(Type type, object parameter) return ExceptionHelper.ThrowNotSupported(); } + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail() + { + return ExceptionHelper.ThrowNotSupported(); + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// The navigation parameter to pass to the target page; must have a basic type (string, char, numeric, or GUID). + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(object parameter) + { + return ExceptionHelper.ThrowNotSupported(); + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(Type type) + { + return ExceptionHelper.ThrowNotSupported(); + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// The navigation parameter to pass to the target page; must have a basic type (string, char, numeric, or GUID). + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(Type type, object parameter) + { + return ExceptionHelper.ThrowNotSupported(); + } + /// /// Gets a value indicating whether there is at least one entry in back navigation history. /// diff --git a/src/Cimbalino.Toolkit (WP81)/Cimbalino.Toolkit (WP81).csproj b/src/Cimbalino.Toolkit (WP81)/Cimbalino.Toolkit (WP81).csproj index 28322d5..6b388b5 100644 --- a/src/Cimbalino.Toolkit (WP81)/Cimbalino.Toolkit (WP81).csproj +++ b/src/Cimbalino.Toolkit (WP81)/Cimbalino.Toolkit (WP81).csproj @@ -155,6 +155,9 @@ Controls\ExtendedPageBase.cs + + Controls\IMasterDetailFrame.cs + Converters\BooleanToBrushConverter.cs diff --git a/src/Cimbalino.Toolkit (WPA81)/Cimbalino.Toolkit (WPA81).csproj b/src/Cimbalino.Toolkit (WPA81)/Cimbalino.Toolkit (WPA81).csproj index dfab1ea..5c57fd3 100644 --- a/src/Cimbalino.Toolkit (WPA81)/Cimbalino.Toolkit (WPA81).csproj +++ b/src/Cimbalino.Toolkit (WPA81)/Cimbalino.Toolkit (WPA81).csproj @@ -126,6 +126,9 @@ Controls\ExtendedPageBase.cs + + Controls\IMasterDetailFrame.cs + Converters\BooleanToBrushConverter.cs diff --git a/src/Cimbalino.Toolkit (WPA81)/Services/NavigationService.cs b/src/Cimbalino.Toolkit (WPA81)/Services/NavigationService.cs index 84f2cbf..d36c2c6 100644 --- a/src/Cimbalino.Toolkit (WPA81)/Services/NavigationService.cs +++ b/src/Cimbalino.Toolkit (WPA81)/Services/NavigationService.cs @@ -15,6 +15,8 @@ #if WINDOWS_PHONE_APP using System; using System.Collections.Generic; +using System.Linq; +using Cimbalino.Toolkit.Controls; using Cimbalino.Toolkit.Extensions; using Cimbalino.Toolkit.Helpers; using Windows.Phone.UI.Input; @@ -23,6 +25,8 @@ #elif WINDOWS_UWP using System; using System.Collections.Generic; +using System.Linq; +using Cimbalino.Toolkit.Controls; using Cimbalino.Toolkit.Extensions; using Cimbalino.Toolkit.Helpers; using Windows.Phone.UI.Input; @@ -32,6 +36,7 @@ #else using System; using System.Collections.Generic; +using System.Linq; using Cimbalino.Toolkit.Extensions; using Cimbalino.Toolkit.Helpers; using Windows.UI.Xaml; @@ -204,6 +209,48 @@ public virtual bool Navigate(Type type, object parameter) return GetFrame()?.Navigate(type, parameter) ?? false; } + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail() + { + return Navigate(typeof(T)); + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// The navigation parameter to pass to the target page; must have a basic type (string, char, numeric, or GUID). + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(object parameter) + { + return Navigate(typeof(T), parameter); + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(Type type) + { + return GetDetailFrame()?.Navigate(type) ?? false; + } + + /// + /// Navigates the detail frame to the content specified by the type reference. + /// + /// The page to navigate to, specified as a type reference to its partial class type. + /// The navigation parameter to pass to the target page; must have a basic type (string, char, numeric, or GUID). + /// true if navigation is not canceled; otherwise, false. + public bool NavigateDetail(Type type, object parameter) + { + return GetDetailFrame()?.Navigate(type, parameter) ?? false; + } + /// /// Gets a value indicating whether there is at least one entry in back navigation history. /// @@ -332,6 +379,20 @@ private Frame GetFrame() return frame; } + private Frame GetDetailFrame() + { + var detailFrame = (Frame)null; + + var page = GetFrame()?.Content as Page; + + if (page != null) + { + detailFrame = page.GetVisualDescendents().FirstOrDefault(); + } + + return detailFrame; + } + private void Frame_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) { CurrentParameter = e.Parameter; @@ -386,38 +447,57 @@ private void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e) private bool HandleBackKeyPress() { - var handled = false; + var handled = (GetDetailFrame() as IMasterDetailFrame)?.HandleBackKeyPress() ?? false; - var eventArgs = new NavigationServiceBackKeyPressedEventArgs(); + if (!handled) + { + var eventArgs = new NavigationServiceBackKeyPressedEventArgs(); - RaiseBackKeyPressed(eventArgs); + RaiseBackKeyPressed(eventArgs); - switch (eventArgs.Behavior) - { - case NavigationServiceBackKeyPressedBehavior.GoBack: - var frame = GetFrame(); + switch (eventArgs.Behavior) + { + case NavigationServiceBackKeyPressedBehavior.GoBack: + var frame = GetFrame(); + + if (frame?.CanGoBack ?? false) + { + frame.GoBack(); + handled = true; + } + break; - if (frame?.CanGoBack ?? false) - { - frame.GoBack(); + case NavigationServiceBackKeyPressedBehavior.HideApp: + break; + + case NavigationServiceBackKeyPressedBehavior.ExitApp: handled = true; - } - break; + Application.Current?.Exit(); + break; + + case NavigationServiceBackKeyPressedBehavior.DoNothing: + handled = true; + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } - case NavigationServiceBackKeyPressedBehavior.HideApp: - break; + return handled; + } - case NavigationServiceBackKeyPressedBehavior.ExitApp: - handled = true; - Application.Current?.Exit(); - break; + private bool HandleDetailBackKeyPress() + { + var handled = false; + + var detailFrame = GetDetailFrame(); - case NavigationServiceBackKeyPressedBehavior.DoNothing: - handled = true; - break; + if (detailFrame != null && detailFrame.CanGoBack) + { + detailFrame.GoBack(); - default: - throw new ArgumentOutOfRangeException(); + handled = true; } return handled; diff --git a/src/Cimbalino.Toolkit (Win81)/Cimbalino.Toolkit (Win81).csproj b/src/Cimbalino.Toolkit (Win81)/Cimbalino.Toolkit (Win81).csproj index ddf51cb..05dc131 100644 --- a/src/Cimbalino.Toolkit (Win81)/Cimbalino.Toolkit (Win81).csproj +++ b/src/Cimbalino.Toolkit (Win81)/Cimbalino.Toolkit (Win81).csproj @@ -150,6 +150,9 @@ Controls\ExtendedPageBase.cs + + Controls\IMasterDetailFrame.cs + Converters\BooleanToBrushConverter.cs diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Cimbalino.Toolkit.Controls (UWP).csproj b/src/Cimbalino.Toolkit.Controls (UWP)/Cimbalino.Toolkit.Controls (UWP).csproj index 62df8f2..a43d91b 100644 --- a/src/Cimbalino.Toolkit.Controls (UWP)/Cimbalino.Toolkit.Controls (UWP).csproj +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Cimbalino.Toolkit.Controls (UWP).csproj @@ -127,6 +127,8 @@ + + diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerMenuButton.cs b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerMenuButton.cs index ea0ee98..ab431cd 100644 --- a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerMenuButton.cs +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerMenuButton.cs @@ -79,7 +79,7 @@ public Type NavigationSourcePageType /// The navigation parameter property /// public static readonly DependencyProperty NavigationParameterProperty = DependencyProperty.Register( - nameof(NavigationParameter), typeof(object), typeof(HamburgerMenuButton), new PropertyMetadata(default(object))); + nameof(NavigationParameter), typeof(object), typeof(HamburgerMenuButton), new PropertyMetadata(null)); /// /// Gets or sets the navigation parameter. diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerTitleBar.cs b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerTitleBar.cs index 3545e7c..416ce15 100644 --- a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerTitleBar.cs +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/HamburgerTitleBar.cs @@ -89,7 +89,7 @@ protected override void OnApplyTemplate() base.OnApplyTemplate(); - _menuButton = (Button)GetTemplateChild("MenuButton"); + _menuButton = (Button)this.GetTemplateChild("MenuButton"); if (_menuButton != null) { diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrame.cs b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrame.cs new file mode 100644 index 0000000..b9c9e6a --- /dev/null +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrame.cs @@ -0,0 +1,173 @@ +// **************************************************************************** +// +// Copyright © Pedro Lamas 2014 +// +// **************************************************************************** +// Pedro Lamas +// pedrolamas@gmail.com +// Cimbalino.Toolkit.Controls +// http://www.pedrolamas.com +// +// See license.txt in this solution or http://www.pedrolamas.com/license_MIT.txt +// +// **************************************************************************** + +using System; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; + +namespace Cimbalino.Toolkit.Controls +{ + /// + /// A master detail frame. + /// + [TemplateVisualState(Name = DisplayModeStatesName, GroupName = DefaultStateName)] + [TemplateVisualState(Name = DisplayModeStatesName, GroupName = CompactMasterStateName)] + public class MasterDetailFrame : Frame, IMasterDetailFrame + { + private const string DisplayModeStatesName = "DisplayModeStates"; + private const string DefaultStateName = "Default"; + private const string CompactMasterStateName = "CompactMaster"; + private const string CompactDetailStateName = "CompactDetail"; + + /// + /// Gets or sets the master. + /// + /// The master. + public UIElement Master + { + get { return (UIElement)GetValue(MasterProperty); } + set { SetValue(MasterProperty, value); } + } + + /// + /// Identifier for the dependency property. + /// + public static readonly DependencyProperty MasterProperty = + DependencyProperty.Register(nameof(Master), typeof(UIElement), typeof(MasterDetailFrame), new PropertyMetadata(null)); + + /// + /// Gets or sets the background of the master. + /// + /// The background of the master. + public Brush MasterBackground + { + get { return (Brush)GetValue(MasterBackgroundProperty); } + set { SetValue(MasterBackgroundProperty, value); } + } + + /// + /// Identifier for the dependency property. + /// + public static readonly DependencyProperty MasterBackgroundProperty = + DependencyProperty.Register(nameof(MasterBackground), typeof(Brush), typeof(MasterDetailFrame), new PropertyMetadata(null)); + + /// + /// Gets or sets the width of the master. + /// + /// The width of the master. + public double MasterLength + { + get { return (double)GetValue(MasterLengthProperty); } + set { SetValue(MasterLengthProperty, value); } + } + + /// + /// Identifier for the dependency property. + /// + public static readonly DependencyProperty MasterLengthProperty = + DependencyProperty.Register(nameof(MasterLength), typeof(double), typeof(MasterDetailFrame), new PropertyMetadata(0)); + + /// + /// Gets or sets the display mode. + /// + /// The display mode. + public MasterDetailFrameDisplayMode DisplayMode + { + get { return (MasterDetailFrameDisplayMode)GetValue(DisplayModeProperty); } + set { SetValue(DisplayModeProperty, value); } + } + + /// + /// Identifier for the dependency property. + /// + public static readonly DependencyProperty DisplayModeProperty = + DependencyProperty.Register(nameof(DisplayMode), typeof(MasterDetailFrameDisplayMode), typeof(MasterDetailFrame), new PropertyMetadata(MasterDetailFrameDisplayMode.Normal, OnDisplayModeChanged)); + + private static void OnDisplayModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var masterDetailFrame = (MasterDetailFrame)d; + + masterDetailFrame.Update(); + } + + /// + /// Initializes a new instance of the class. + /// + public MasterDetailFrame() + { + DefaultStyleKey = typeof(MasterDetailFrame); + + if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) + { + return; + } + + this.Navigated += MasterDetailFrame_Navigated; + + this.Navigate(typeof(Page)); + } + + /// + /// When overridden in a derived class, is invoked whenever application code or internal processes call ApplyTemplate. + /// + protected override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + Update(); + } + + private void Update() + { + switch (DisplayMode) + { + case MasterDetailFrameDisplayMode.Normal: + VisualStateManager.GoToState(this, DefaultStateName, true); + break; + + case MasterDetailFrameDisplayMode.Compact: + VisualStateManager.GoToState(this, this.CanGoBack ? CompactDetailStateName : CompactMasterStateName, true); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + + private void MasterDetailFrame_Navigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) + { + while (this.BackStackDepth > 1) + { + this.BackStack.RemoveAt(this.BackStackDepth - 1); + } + + Update(); + } + + bool IMasterDetailFrame.HandleBackKeyPress() + { + var handled = false; + + if (DisplayMode == MasterDetailFrameDisplayMode.Compact && this.CanGoBack) + { + this.GoBack(); + + handled = true; + } + + return handled; + } + } +} \ No newline at end of file diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrameDisplayMode.cs b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrameDisplayMode.cs new file mode 100644 index 0000000..464021a --- /dev/null +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Controls/MasterDetailFrameDisplayMode.cs @@ -0,0 +1,32 @@ +// **************************************************************************** +// +// Copyright © Pedro Lamas 2014 +// +// **************************************************************************** +// Pedro Lamas +// pedrolamas@gmail.com +// Cimbalino.Toolkit +// http://www.pedrolamas.com +// +// See license.txt in this solution or http://www.pedrolamas.com/license_MIT.txt +// +// **************************************************************************** + +namespace Cimbalino.Toolkit.Controls +{ + /// + /// Represents the display mode. + /// + public enum MasterDetailFrameDisplayMode + { + /// + /// Normal display mode. + /// + Normal, + + /// + /// Compact display mode. + /// + Compact + } +} \ No newline at end of file diff --git a/src/Cimbalino.Toolkit.Controls (UWP)/Themes/Generic.xaml b/src/Cimbalino.Toolkit.Controls (UWP)/Themes/Generic.xaml index b6dfb5b..f40f451 100644 --- a/src/Cimbalino.Toolkit.Controls (UWP)/Themes/Generic.xaml +++ b/src/Cimbalino.Toolkit.Controls (UWP)/Themes/Generic.xaml @@ -37,6 +37,14 @@ + @@ -69,15 +77,6 @@ - - @@ -96,6 +95,20 @@ + + + + + + @@ -187,20 +200,6 @@ - - - - - - @@ -257,40 +256,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -336,6 +301,105 @@ Padding="{TemplateBinding Padding}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +