From 3fec6506d5603867416d0878de566de37578fd09 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 21:56:06 +0200 Subject: [PATCH 01/38] Add WinUi and WPF licenses [skip ci] --- src/Wpf.Ui/License - Microsoft.Ui.Xaml.txt | 21 +++++++++++++++++ ...ense - Windows Presentation Foundation.txt | 23 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/Wpf.Ui/License - Microsoft.Ui.Xaml.txt create mode 100644 src/Wpf.Ui/License - Windows Presentation Foundation.txt diff --git a/src/Wpf.Ui/License - Microsoft.Ui.Xaml.txt b/src/Wpf.Ui/License - Microsoft.Ui.Xaml.txt new file mode 100644 index 000000000..d1ca00f20 --- /dev/null +++ b/src/Wpf.Ui/License - Microsoft.Ui.Xaml.txt @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE \ No newline at end of file diff --git a/src/Wpf.Ui/License - Windows Presentation Foundation.txt b/src/Wpf.Ui/License - Windows Presentation Foundation.txt new file mode 100644 index 000000000..a616ed188 --- /dev/null +++ b/src/Wpf.Ui/License - Windows Presentation Foundation.txt @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 8c5fa79087e44bea5e6a4b987d7b24e1e3339aa4 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 21:56:35 +0200 Subject: [PATCH 02/38] Prepare base classes for NavigationView --- .../Controls/Interfaces/INavigationView.cs | 89 +++++++++++ .../Navigation/NavigationView.Events.cs | 79 ++++++++++ .../Navigation/NavigationView.Navigation.cs | 20 +++ .../Navigation/NavigationView.Properties.cs | 141 ++++++++++++++++++ .../NavigationViewBackButtonVisible.cs | 30 ++++ .../Navigation/NavigationViewEvent.cs | 22 +++ .../Controls/Navigation/NavigationViewItem.cs | 18 +++ .../Navigation/NavigationViewItemHeader.cs | 18 +++ .../Navigation/NavigationViewItemSeparator.cs | 18 +++ .../Controls/Navigation/NavigationViewList.cs | 20 +++ src/Wpf.Ui/Wpf.Ui.csproj | 6 + 11 files changed, 461 insertions(+) create mode 100644 src/Wpf.Ui/Controls/Interfaces/INavigationView.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewBackButtonVisible.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewEvent.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewList.cs diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs new file mode 100644 index 000000000..d7209edd5 --- /dev/null +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs @@ -0,0 +1,89 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Collections.Generic; +using Wpf.Ui.Controls.Navigation; + +namespace Wpf.Ui.Controls.Interfaces; + +/// +/// Represents a container that enables navigation of app content. It has a header, a view for the main content, and a menu pane for navigation commands. +/// +public interface INavigationView +{ + /// + /// Gets the collection of menu items displayed in the NavigationView. + /// + IList MenuItems { get; set; } + + /// + /// Gets or sets an object source used to generate the content of the NavigationView menu. + /// + object MenuItemsSource { get; set; } + + /// + /// Gets the list of objects to be used as navigation items in the footer menu. + /// + IList FooterMenuItems { get; set; } + + /// + /// Gets or sets the object that represents the navigation items to be used in the footer menu. + /// + object FooterMenuItemsSource { get; set; } + + /// + /// Gets or sets a UI element that is shown at the top of the control, below the pane if PaneDisplayMode is Top. + /// + object ContentOverlay { get; set; } + + /// + /// Gets or sets a value that indicates whether the back button is enabled or disabled. + /// + bool IsBackEnabled { get; set; } + + /// + /// Gets or sets a value that indicates whether the back button is visible or not. + /// Default value is "Auto", which indicates that button visibility depends on the DisplayMode setting of the NavigationView. + /// + NavigationViewBackButtonVisible IsBackButtonVisible { get; set; } + + /// + /// Gets or sets a value that specifies whether the NavigationView pane is expanded to its full width. + /// + bool IsPaneOpen { get; set; } + + /// + /// Gets or sets a value that determines whether the pane is shown. + /// + bool IsPaneVisible { get; set; } + + /// + /// Occurs when the NavigationView pane is opened. + /// + event NavigationViewEvent PaneOpened; + + /// + /// Occurs when the NavigationView pane is closed. + /// + event NavigationViewEvent PaneClosed; + + /// + /// Occurs when the currently selected item changes. + /// + event NavigationViewEvent SelectionChanged; + + /// + /// Occurs when an item in the menu receives an interaction such as a click or tap. + /// + event NavigationViewEvent ItemInvoked; + + /// + /// Occurs when the back button receives an interaction such as a click or tap. + /// + event NavigationViewEvent BackRequested; +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs new file mode 100644 index 000000000..90feb308d --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs @@ -0,0 +1,79 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Windows; + +namespace Wpf.Ui.Controls.Navigation; + +public partial class NavigationView +{ + /// + /// Property for . + /// + public static readonly RoutedEvent PaneOpenedEvent = EventManager.RegisterRoutedEvent(nameof(PaneOpened), + RoutingStrategy.Bubble, typeof(NavigationViewEvent), typeof(NavigationView)); + + /// + /// Property for . + /// + public static readonly RoutedEvent PaneClosedEvent = EventManager.RegisterRoutedEvent(nameof(PaneClosed), + RoutingStrategy.Bubble, typeof(NavigationViewEvent), typeof(NavigationView)); + + /// + /// Property for . + /// + public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent(nameof(SelectionChanged), + RoutingStrategy.Bubble, typeof(NavigationViewEvent), typeof(NavigationView)); + + /// + /// Property for . + /// + public static readonly RoutedEvent ItemInvokedEvent = EventManager.RegisterRoutedEvent(nameof(ItemInvoked), + RoutingStrategy.Bubble, typeof(NavigationViewEvent), typeof(NavigationView)); + + /// + /// Property for . + /// + public static readonly RoutedEvent BackRequestedEvent = EventManager.RegisterRoutedEvent(nameof(BackRequested), + RoutingStrategy.Bubble, typeof(NavigationViewEvent), typeof(NavigationView)); + + /// + public event NavigationViewEvent PaneOpened + { + add => AddHandler(PaneOpenedEvent, value); + remove => RemoveHandler(PaneOpenedEvent, value); + } + + /// + public event NavigationViewEvent PaneClosed + { + add => AddHandler(PaneClosedEvent, value); + remove => RemoveHandler(PaneClosedEvent, value); + } + + /// + public event NavigationViewEvent SelectionChanged + { + add => AddHandler(SelectionChangedEvent, value); + remove => RemoveHandler(SelectionChangedEvent, value); + } + + /// + public event NavigationViewEvent ItemInvoked + { + add => AddHandler(ItemInvokedEvent, value); + remove => RemoveHandler(ItemInvokedEvent, value); + } + + /// + public event NavigationViewEvent BackRequested + { + add => AddHandler(BackRequestedEvent, value); + remove => RemoveHandler(BackRequestedEvent, value); + } +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs new file mode 100644 index 000000000..db35d70cc --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs @@ -0,0 +1,20 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using Wpf.Ui.Controls.Interfaces; + +namespace Wpf.Ui.Controls.Navigation; + +// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationview?view=winrt-22621 + +/// +/// Represents a container that enables navigation of app content. It has a header, a view for the main content, and a menu pane for navigation commands. +/// +public partial class NavigationView : System.Windows.Controls.Control, INavigationView +{ +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs new file mode 100644 index 000000000..e551a5d0d --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs @@ -0,0 +1,141 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Collections.Generic; +using System.Windows; + +namespace Wpf.Ui.Controls.Navigation; + +public partial class NavigationView +{ + /// + /// Property for . + /// + public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(nameof(MenuItems), + typeof(IList), typeof(NavigationView), + new FrameworkPropertyMetadata(new List())); + + /// + /// Property for . + /// + public static readonly DependencyProperty MenuItemsSourceProperty = DependencyProperty.Register(nameof(MenuItemsSource), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + + /// + /// Property for . + /// + public static readonly DependencyProperty FooterMenuItemsProperty = DependencyProperty.Register(nameof(FooterMenuItemsProperty), + typeof(IList), typeof(NavigationView), + new FrameworkPropertyMetadata(new List())); + + /// + /// Property for . + /// + public static readonly DependencyProperty FooterMenuItemsSourceProperty = DependencyProperty.Register(nameof(FooterMenuItemsSource), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + + /// + /// Property for . + /// + public static readonly DependencyProperty ContentOverlayProperty = DependencyProperty.Register(nameof(ContentOverlay), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsBackEnabledProperty = DependencyProperty.Register(nameof(IsBackEnabled), + typeof(bool), typeof(NavigationView), + new FrameworkPropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsBackButtonVisibleProperty = DependencyProperty.Register(nameof(IsBackButtonVisible), + typeof(NavigationViewBackButtonVisible), typeof(NavigationView), + new FrameworkPropertyMetadata(NavigationViewBackButtonVisible.Auto)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsPaneOpenProperty = DependencyProperty.Register(nameof(IsPaneOpen), + typeof(bool), typeof(NavigationView), + new FrameworkPropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsPaneVisibleProperty = DependencyProperty.Register(nameof(IsPaneVisible), + typeof(bool), typeof(NavigationView), + new FrameworkPropertyMetadata(false)); + + /// + public IList MenuItems + { + get => (IList)GetValue(MenuItemsProperty); + set => SetValue(MenuItemsProperty, value); + } + + /// + public object MenuItemsSource + { + get => GetValue(MenuItemsSourceProperty); + set => SetValue(MenuItemsSourceProperty, value); + } + + /// + public IList FooterMenuItems + { + get => (IList)GetValue(FooterMenuItemsProperty); + set => SetValue(FooterMenuItemsProperty, value); + } + + /// + public object FooterMenuItemsSource + { + get => GetValue(FooterMenuItemsSourceProperty); + set => SetValue(FooterMenuItemsSourceProperty, value); + } + + /// + public object ContentOverlay + { + get => GetValue(ContentOverlayProperty); + set => SetValue(ContentOverlayProperty, value); + } + + /// + public bool IsBackEnabled + { + get => (bool)GetValue(IsBackEnabledProperty); + set => SetValue(IsBackEnabledProperty, value); + } + + /// + public NavigationViewBackButtonVisible IsBackButtonVisible + { + get => (NavigationViewBackButtonVisible)GetValue(IsBackButtonVisibleProperty); + set => SetValue(IsBackButtonVisibleProperty, value); + } + + /// + public bool IsPaneOpen + { + get => (bool)GetValue(IsPaneOpenProperty); + set => SetValue(IsPaneOpenProperty, value); + } + + /// + public bool IsPaneVisible + { + get => (bool)GetValue(IsPaneVisibleProperty); + set => SetValue(IsPaneVisibleProperty, value); + } +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewBackButtonVisible.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewBackButtonVisible.cs new file mode 100644 index 000000000..6867deeb5 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewBackButtonVisible.cs @@ -0,0 +1,30 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +/// +/// Defines constants that specify whether the back button is visible in NavigationView. +/// +public enum NavigationViewBackButtonVisible +{ + /// + /// Do not display the back button in NavigationView, and do not reserve space for it in layout. + /// + Collapsed, + + /// + /// Display the back button in NavigationView. + /// + Visible, + + /// + /// The system chooses whether or not to display the back button, depending on the device/form factor. On phones, tablets, desktops, and hubs, the back button is visible. On Xbox/TV, the back button is collapsed. + /// + Auto +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewEvent.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewEvent.cs new file mode 100644 index 000000000..eacce83bf --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewEvent.cs @@ -0,0 +1,22 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Diagnostics.CodeAnalysis; +using System.Windows; + +namespace Wpf.Ui.Controls.Navigation; + +/// +/// Event triggered by NavigationView. +/// +/// Current navigation instance. +#if NET5_0_OR_GREATER +public delegate void NavigationViewEvent([NotNull] object sender, RoutedEventArgs e); +#else +public delegate void NavigationViewEvent(object sender, RoutedEventArgs e); +#endif diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs new file mode 100644 index 000000000..6e1e370df --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs @@ -0,0 +1,18 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitem?view=winrt-22621 + +/// +/// Represents the container for an item in a NavigationView control. +/// +public class NavigationViewItem : System.Windows.Controls.Control +{ +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs new file mode 100644 index 000000000..9d98a7266 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs @@ -0,0 +1,18 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitemheader?view=winrt-22621 + +/// +/// Represents a header for a group of menu items in a NavigationMenu. +/// +public class NavigationViewItemHeader : System.Windows.Controls.Control +{ +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs new file mode 100644 index 000000000..0cf5835b7 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs @@ -0,0 +1,18 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitemseparator?view=winrt-22621 + +/// +/// Represents a line that separates menu items in a NavigationMenu. +/// +public class NavigationViewItemSeparator : System.Windows.Controls.Separator +{ +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewList.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewList.cs new file mode 100644 index 000000000..0166bef9b --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewList.cs @@ -0,0 +1,20 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Collections.ObjectModel; + +namespace Wpf.Ui.Controls.Navigation; + +// https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewlist?view=winrt-22621 + +/// +/// Represents a control that displays menu items in a NavigationView control. +/// +public class NavigationViewList : ObservableCollection +{ +} diff --git a/src/Wpf.Ui/Wpf.Ui.csproj b/src/Wpf.Ui/Wpf.Ui.csproj index c723d1d40..c30de4143 100644 --- a/src/Wpf.Ui/Wpf.Ui.csproj +++ b/src/Wpf.Ui/Wpf.Ui.csproj @@ -49,6 +49,12 @@ + + PreserveNewest + + + PreserveNewest + PreserveNewest From 9337ba4c0802580123fd97e9652540e83eafdc39 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 22:16:48 +0200 Subject: [PATCH 03/38] Throw away all the old navigation, lets start fresh --- src/Wpf.Ui/Common/NavigationType.cs | 13 - src/Wpf.Ui/Common/RoutedNavigationEvent.cs | 19 - .../Common/RoutedNavigationEventArgs.cs | 32 - src/Wpf.Ui/Controls/Breadcrumb.cs | 80 -- src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 218 ----- .../Controls/Interfaces/INavigationControl.cs | 13 - .../Controls/Interfaces/INavigationItem.cs | 58 -- .../Navigation/NavigationBackButton.cs | 39 - .../Controls/Navigation/NavigationBase.cs | 722 --------------- .../Controls/Navigation/NavigationHeader.bmp | Bin 824 -> 0 bytes .../Controls/Navigation/NavigationHeader.cs | 97 -- .../Navigation/NavigationSeparator.bmp | Bin 824 -> 0 bytes .../Navigation/NavigationSeparator.cs | 16 - src/Wpf.Ui/Controls/NavigationCompact.bmp | Bin 824 -> 0 bytes src/Wpf.Ui/Controls/NavigationCompact.cs | 68 -- src/Wpf.Ui/Controls/NavigationFluent.bmp | Bin 824 -> 0 bytes src/Wpf.Ui/Controls/NavigationFluent.cs | 19 - src/Wpf.Ui/Controls/NavigationItem.bmp | Bin 824 -> 0 bytes src/Wpf.Ui/Controls/NavigationItem.cs | 386 -------- src/Wpf.Ui/Controls/NavigationStore.bmp | Bin 824 -> 0 bytes src/Wpf.Ui/Controls/NavigationStore.cs | 19 - src/Wpf.Ui/Controls/NavigationView.cs | 70 -- .../Mvvm/Contracts/INavigationService.cs | 65 -- .../Mvvm/Contracts/INavigationWindow.cs | 51 -- src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 97 -- .../Services/Internal/NavigationService.cs | 865 ------------------ .../Internal/NavigationServiceActivator.cs | 166 ---- .../Internal/NavigationServiceExtraData.cs | 27 - .../Internal/NavigationServiceItem.cs | 71 -- src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml | 85 -- src/Wpf.Ui/Styles/Controls/Navigation.xaml | 71 -- .../Styles/Controls/NavigationBackButton.xaml | 90 -- .../Styles/Controls/NavigationCompact.xaml | 408 --------- .../Styles/Controls/NavigationFluent.xaml | 316 ------- .../Styles/Controls/NavigationHeader.xaml | 70 -- .../Styles/Controls/NavigationSeparator.xaml | 35 - .../Styles/Controls/NavigationStore.xaml | 354 ------- .../Styles/Controls/NavigationView.xaml | 91 -- src/Wpf.Ui/Styles/Wpf.Ui.xaml | 9 - src/Wpf.Ui/Wpf.Ui.csproj | 10 - 40 files changed, 4750 deletions(-) delete mode 100644 src/Wpf.Ui/Common/NavigationType.cs delete mode 100644 src/Wpf.Ui/Common/RoutedNavigationEvent.cs delete mode 100644 src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs delete mode 100644 src/Wpf.Ui/Controls/Breadcrumb.cs delete mode 100644 src/Wpf.Ui/Controls/Interfaces/INavigation.cs delete mode 100644 src/Wpf.Ui/Controls/Interfaces/INavigationControl.cs delete mode 100644 src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationBase.cs delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationHeader.bmp delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationHeader.cs delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationSeparator.bmp delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationSeparator.cs delete mode 100644 src/Wpf.Ui/Controls/NavigationCompact.bmp delete mode 100644 src/Wpf.Ui/Controls/NavigationCompact.cs delete mode 100644 src/Wpf.Ui/Controls/NavigationFluent.bmp delete mode 100644 src/Wpf.Ui/Controls/NavigationFluent.cs delete mode 100644 src/Wpf.Ui/Controls/NavigationItem.bmp delete mode 100644 src/Wpf.Ui/Controls/NavigationItem.cs delete mode 100644 src/Wpf.Ui/Controls/NavigationStore.bmp delete mode 100644 src/Wpf.Ui/Controls/NavigationStore.cs delete mode 100644 src/Wpf.Ui/Controls/NavigationView.cs delete mode 100644 src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs delete mode 100644 src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs delete mode 100644 src/Wpf.Ui/Mvvm/Services/NavigationService.cs delete mode 100644 src/Wpf.Ui/Services/Internal/NavigationService.cs delete mode 100644 src/Wpf.Ui/Services/Internal/NavigationServiceActivator.cs delete mode 100644 src/Wpf.Ui/Services/Internal/NavigationServiceExtraData.cs delete mode 100644 src/Wpf.Ui/Services/Internal/NavigationServiceItem.cs delete mode 100644 src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/Navigation.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationBackButton.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationCompact.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationFluent.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationHeader.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationSeparator.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationStore.xaml delete mode 100644 src/Wpf.Ui/Styles/Controls/NavigationView.xaml diff --git a/src/Wpf.Ui/Common/NavigationType.cs b/src/Wpf.Ui/Common/NavigationType.cs deleted file mode 100644 index 8876e9b7b..000000000 --- a/src/Wpf.Ui/Common/NavigationType.cs +++ /dev/null @@ -1,13 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -namespace Wpf.Ui.Common; - -public enum NavigationType -{ - Fluent, - Compact, - Store -} diff --git a/src/Wpf.Ui/Common/RoutedNavigationEvent.cs b/src/Wpf.Ui/Common/RoutedNavigationEvent.cs deleted file mode 100644 index bdaace6fd..000000000 --- a/src/Wpf.Ui/Common/RoutedNavigationEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System.Diagnostics.CodeAnalysis; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Common; - -/// -/// Event triggered on successful navigation. -/// -/// Current navigation instance. -#if NET5_0_OR_GREATER -public delegate void RoutedNavigationEvent([NotNull] INavigation sender, RoutedNavigationEventArgs e); -#else -public delegate void RoutedNavigationEvent(INavigation sender, RoutedNavigationEventArgs e); -#endif diff --git a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs b/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs deleted file mode 100644 index ae124110c..000000000 --- a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs +++ /dev/null @@ -1,32 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System.Windows; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Common; - -/// -/// with additional . -/// -public class RoutedNavigationEventArgs : RoutedEventArgs -{ - /// - /// Currently displayed page. - /// - public INavigationItem CurrentPage { get; set; } - - /// - /// Constructor for . - /// - /// The new value that the SourceProperty is being set to. - /// The new value that the Property is being set to. - /// Currently displayed page. - public RoutedNavigationEventArgs(RoutedEvent routedEvent, object source, INavigationItem currentPage) : base( - routedEvent, source) - { - CurrentPage = currentPage; - } -} diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs deleted file mode 100644 index cb0b089ef..000000000 --- a/src/Wpf.Ui/Controls/Breadcrumb.cs +++ /dev/null @@ -1,80 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Windows; -using Wpf.Ui.Common; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Controls; - -/// -/// Displays the name of the current and it's parents that can be navigated using . -/// -public class Breadcrumb : System.Windows.Controls.Control -{ - /// - /// Property for . - /// - public static readonly DependencyProperty CurrentProperty = DependencyProperty.Register(nameof(Current), - typeof(string), typeof(Breadcrumb), new PropertyMetadata(String.Empty)); - - /// - /// Property for . - /// - public static readonly DependencyProperty NavigationProperty = DependencyProperty.Register(nameof(Navigation), - typeof(INavigation), typeof(Breadcrumb), - new PropertyMetadata(null, OnNavigationChanged)); - - /// - /// based on which displays the titles. - /// - public string Current - { - get => (string)GetValue(CurrentProperty); - set => SetValue(CurrentProperty, value); - } - - /// - /// based on which displays the titles. - /// - public INavigation Navigation - { - get => GetValue(NavigationProperty) as INavigation; - set => SetValue(NavigationProperty, value); - } - - protected virtual void OnNavigated(INavigation sender, RoutedNavigationEventArgs e) - { -#if DEBUG - System.Diagnostics.Debug.WriteLine($"INFO | {typeof(Breadcrumb)} builded, current nav: {Navigation.GetType()}", "Wpf.Ui.Breadcrumb"); -#endif - - //TODO: Navigate with previous levels - - if (Navigation?.Current is not INavigationItem item) - return; - - var pageName = item.Content as string; - - if (String.IsNullOrEmpty(pageName)) - return; - - Current = pageName; - } - - protected virtual void OnNavigationChanged() - { - Navigation.Navigated += OnNavigated; - } - - private static void OnNavigationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not Breadcrumb breadcrumb) - return; - - breadcrumb.OnNavigationChanged(); - } -} diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs deleted file mode 100644 index 3e2592e12..000000000 --- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs +++ /dev/null @@ -1,218 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Windows.Controls; -using Wpf.Ui.Animations; -using Wpf.Ui.Common; -using Wpf.Ui.Mvvm.Contracts; - -namespace Wpf.Ui.Controls.Interfaces; - -/// -/// Represents navigation class. -/// -public interface INavigation -{ - /// - /// Service providing views. - /// - IPageService PageService { get; set; } - - /// - /// Navigation item ID of the current page. - /// If set to a value less than , no will be loaded during initialization. - /// - int SelectedPageIndex { get; set; } - - /// - /// Navigation item ID of the previous page. - /// - int PreviousPageIndex { get; } - - /// - /// Creates an instance of all pages defined with after the is loaded. - /// - bool Precache { get; set; } - - /// - /// Indicates the possibility of navigation back - /// - bool CanGoBack { get; } - - /// - /// Currently used item like . - /// - INavigationItem Current { get; } - - /// - /// Gets or sets the in which the will be loaded after navigation. - /// - [Bindable(true)] - Frame Frame { get; set; } - - /// - /// Gets or sets the list of that will be displayed on the navigation. - /// - [Bindable(true)] - ObservableCollection Items { get; set; } - - /// - /// Gets or sets the list of which will be displayed at the bottom of the navigation and will not be scrolled. - /// - [Bindable(true)] - ObservableCollection Footer { get; set; } - - /// - /// Specifies dimension of children stacking. - /// - Orientation Orientation { get; set; } - - /// - /// Gets or sets the that will be triggered during navigation. - /// - [Category("Behavior")] - event RoutedNavigationEvent Navigated; - - /// - /// Gets or sets the that will be triggered during forward navigation. - /// - [Category("Behavior")] - event RoutedNavigationEvent NavigatedForward; - - /// - /// Gets or sets the that will be triggered during backward navigation. - /// - [Category("Behavior")] - event RoutedNavigationEvent NavigatedBackward; - - /// - /// Gets or sets a value deciding how long the effect of the transition between the pages should take. - /// - [Bindable(true), Category("Appearance")] - int TransitionDuration { get; set; } - - /// - /// Gets or sets type of transitions during navigation. - /// - [Bindable(true), Category("Appearance")] - TransitionType TransitionType { get; set; } - - /// - /// Clears all navigation items. - /// - void Flush(); - - /// - /// Clears all initialized instances of the pages. - /// - void ClearCache(); - - /// - /// Navigates to the previous page using the . - /// - /// - bool NavigateBack(); - - /// - /// Navigates to the page using the . - /// - /// Type of the page to navigate. - /// if the operation was successful. - bool Navigate(Type pageType); - - /// - /// Navigates to the page using the . - /// - /// Type of the page to navigate. - /// When an DataContext changes, all data-bound properties (on this element or any other element) whose Bindings use this DataContext will change to reflect the new value. - /// if the operation was successful. - bool Navigate(Type pageType, object dataContext); - - /// - /// Loads a instance into based on the tag of . - /// - /// ID of the page to be loaded. - /// if the operation was successful. - bool Navigate(int pageIndex); - - /// - /// Loads a instance into based on the tag of . - /// - /// ID of the page to be loaded. - /// When an DataContext changes, all data-bound properties (on this element or any other element) whose Bindings use this DataContext will change to reflect the new value. - /// if the operation was successful. - bool Navigate(int pageIndex, object dataContext); - - /// - /// Loads a instance into based on the tag of . - /// - /// to be loaded. - /// if the operation was successful. - bool Navigate(string pageTag); - - /// - /// Loads a instance into based on the tag of . - /// - /// to be loaded. - /// When an DataContext changes, all data-bound properties (on this element or any other element) whose Bindings use this DataContext will change to reflect the new value. - bool Navigate(string pageTag, object dataContext); - - /// - /// Navigate to the given object that is outside the current navigation. - /// - /// The element you want to navigate to a that is not in the or pool. - /// if the operation was successful. - bool NavigateExternal(object frameworkElement); - - /// - /// Navigate to the given object that is outside the current navigation. - /// - /// The element you want to navigate to a that is not in the or pool. - /// Context of the data for data binding. - /// if the operation was successful. - bool NavigateExternal(object frameworkElement, object dataContext); - - /// - /// Navigate to the given that is outside the current navigation. - /// - /// to the element you want to navigate to a that is not in the or pool. - /// if the operation was successful. - bool NavigateExternal(Uri absolutePageUri); - - /// - /// Navigate to the given that is outside the current navigation. - /// - /// to the element you want to navigate to a that is not in the or pool. - /// Context of the data for data binding. - /// if the operation was successful. - bool NavigateExternal(Uri absolutePageUri, object dataContext); - - /// - /// Sets of the page. - /// If the page is not in the Cache, and is defined based on , its object will be created and then its DataContext will be defined. - /// - /// Id of the page from or . - /// Context of the data for data binding. - /// if the operation was successful. - bool SetContext(int pageId, object dataContext); - - /// - /// Sets of the page. - /// If the page is not in the Cache, and is defined based on , its object will be created and then its DataContext will be defined. - /// - /// Tag of the page from or . - /// Context of the data for data binding. - /// if the operation was successful. - bool SetContext(string pageTag, object dataContext); - - /// - /// Tires to set the DataContext for the currently displayed page. - /// - /// Data context to be set. - void SetCurrentContext(object dataContext); -} diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationControl.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationControl.cs deleted file mode 100644 index 3c89b39b4..000000000 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationControl.cs +++ /dev/null @@ -1,13 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -namespace Wpf.Ui.Controls.Interfaces; - -/// -/// An interface element that can be part of a navigation list. -/// -public interface INavigationControl -{ -} diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs deleted file mode 100644 index 216171173..000000000 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs +++ /dev/null @@ -1,58 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.ComponentModel; -using System.Windows; -using System.Windows.Controls; - -namespace Wpf.Ui.Controls.Interfaces; - -/// -/// Navigation element. -/// -public interface INavigationItem -{ - /// - /// Represents a text page identifier that can be navigated with . - /// - string PageTag { get; set; } - - /// - /// Content is the data used to generate the child elements of this control. - /// - object Content { get; } - - /// - /// Gets information whether the current element is active. - /// - bool IsActive { get; set; } - - /// - /// Determines whether an should be cached. - /// - bool Cache { get; set; } - - /// - /// URI of the application or content being navigated to. - /// - Uri PageSource { get; set; } - - /// - /// A inherited from that defines page of the item. - /// - Type PageType { get; set; } - - /// - /// Absolute path to the XAML template based on and . - /// - Uri AbsolutePageSource { get; } - - /// - /// Add / Remove ClickEvent handler - /// - [Category("Behavior")] - event RoutedEventHandler Click; -} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs deleted file mode 100644 index d1ffefb16..000000000 --- a/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs +++ /dev/null @@ -1,39 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -#nullable enable - -using System.ComponentModel; -using System.Windows; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Controls.Navigation; - -/// -/// Inherited from the , used to navigate backwards inside the . -/// -public class NavigationBackButton : System.Windows.Controls.Button -{ - /// - /// Property for . - /// - public static readonly DependencyProperty NavigationProperty = DependencyProperty.Register(nameof(Navigation), - typeof(INavigation), typeof(NavigationBackButton), new PropertyMetadata(null)); - - /// - /// Parent control. - /// - [Bindable(true), Category("Behavior")] - public INavigation? Navigation - { - get => (INavigation)GetValue(NavigationProperty); - set => SetValue(NavigationProperty, value); - } - - public NavigationBackButton() - { - SetValue(CommandProperty, new Common.RelayCommand(_ => Navigation?.NavigateBack(), () => Navigation is not null && Navigation.CanGoBack)); - } -} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs deleted file mode 100644 index bc8ea838c..000000000 --- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs +++ /dev/null @@ -1,722 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -#nullable enable -#pragma warning disable CS8600 -#pragma warning disable CS8603 - -using System; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using Wpf.Ui.Common; -using Wpf.Ui.Controls.Interfaces; -using Wpf.Ui.Mvvm.Contracts; -using Wpf.Ui.Mvvm.Interfaces; - -namespace Wpf.Ui.Controls.Navigation; - -/// -/// Base implementation for the navigation view. -/// -public abstract class NavigationBase : System.Windows.Controls.Control, INavigation -{ - /// - /// Service used for navigation purposes. - /// - private readonly Services.Internal.NavigationService? _navigationService; - - /// - /// Property for . - /// - public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(nameof(Items), - typeof(ObservableCollection), typeof(NavigationBase), - new PropertyMetadata((ObservableCollection)null, OnItemsChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(nameof(Footer), - typeof(ObservableCollection), typeof(NavigationBase), - new PropertyMetadata((ObservableCollection)null, OnFooterChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), - typeof(Orientation), typeof(NavigationBase), - new FrameworkPropertyMetadata(Orientation.Vertical, - FrameworkPropertyMetadataOptions.AffectsMeasure)); - - /// - /// Property for . - /// - public static readonly DependencyProperty FrameProperty = DependencyProperty.Register(nameof(Frame), - typeof(Frame), typeof(NavigationBase), - new PropertyMetadata((Frame)null, OnFrameChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty TransitionDurationProperty = DependencyProperty.Register( - nameof(TransitionDuration), - typeof(int), typeof(NavigationBase), - new PropertyMetadata(300, OnTransitionDurationChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty TransitionTypeProperty = DependencyProperty.Register( - nameof(TransitionType), - typeof(Animations.TransitionType), typeof(NavigationBase), - new PropertyMetadata(Animations.TransitionType.FadeInWithSlide, OnTransitionTypeChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty SelectedPageIndexProperty = DependencyProperty.Register( - nameof(SelectedPageIndex), - typeof(int), typeof(NavigationBase), - new PropertyMetadata(-1)); - - /// - /// Property for . - /// - public static readonly DependencyProperty PrecacheProperty = DependencyProperty.Register( - nameof(Precache), - typeof(bool), typeof(NavigationBase), - new PropertyMetadata(false)); - - /// - /// Attached property for 's to get its parent. - /// - internal static readonly DependencyProperty NavigationParentProperty = DependencyProperty.RegisterAttached( - nameof(NavigationParent), typeof(INavigation), typeof(NavigationBase), - new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); - - /// - public ObservableCollection Items - { - get => GetValue(ItemsProperty) as ObservableCollection; - set => SetValue(ItemsProperty, value); - } - - /// - public ObservableCollection Footer - { - get => GetValue(FooterProperty) as ObservableCollection; - set => SetValue(FooterProperty, value); - } - - /// - [Obsolete("Work in progress.")] - public Orientation Orientation - { - get => (Orientation)GetValue(OrientationProperty); - set => SetValue(OrientationProperty, value); - } - - /// - public int TransitionDuration - { - get => (int)GetValue(TransitionDurationProperty); - set => SetValue(TransitionDurationProperty, value); - } - - /// - public Animations.TransitionType TransitionType - { - get => (Animations.TransitionType)GetValue(TransitionTypeProperty); - set => SetValue(TransitionTypeProperty, value); - } - - /// - public Frame? Frame - { - get => GetValue(FrameProperty) as Frame; - set => SetValue(FrameProperty, value); - } - - /// - public int SelectedPageIndex - { - get => (int)GetValue(SelectedPageIndexProperty); - set => SetValue(SelectedPageIndexProperty, value); - } - - /// - public bool Precache - { - get => (bool)GetValue(PrecacheProperty); - set => SetValue(PrecacheProperty, value); - } - - internal INavigation NavigationParent - { - get => (INavigation)GetValue(NavigationParentProperty); - private set => SetValue(NavigationParentProperty, value); - } - - #region Events - - /// - /// Event triggered when navigate to page. - /// - public static readonly RoutedEvent NavigatedEvent = EventManager.RegisterRoutedEvent(nameof(Navigated), - RoutingStrategy.Bubble, typeof(RoutedNavigationEvent), typeof(NavigationBase)); - - /// - public event RoutedNavigationEvent Navigated - { - add => AddHandler(NavigatedEvent, value); - remove => RemoveHandler(NavigatedEvent, value); - } - - /// - /// Event triggered when navigate to the next page. - /// - public static readonly RoutedEvent NavigatedForwardEvent = - EventManager.RegisterRoutedEvent(nameof(NavigatedForward), RoutingStrategy.Bubble, - typeof(RoutedNavigationEvent), typeof(NavigationBase)); - - /// - public event RoutedNavigationEvent NavigatedForward - { - add => AddHandler(NavigatedForwardEvent, value); - remove => RemoveHandler(NavigatedForwardEvent, value); - } - - /// - /// Event triggered when navigate to the previous page. - /// - public static readonly RoutedEvent NavigatedBackwardEvent = - EventManager.RegisterRoutedEvent(nameof(NavigatedBackward), RoutingStrategy.Bubble, - typeof(RoutedNavigationEvent), typeof(NavigationBase)); - - /// - public event RoutedNavigationEvent NavigatedBackward - { - add => AddHandler(NavigatedBackwardEvent, value); - remove => RemoveHandler(NavigatedBackwardEvent, value); - } - - #endregion - - /// - public IPageService? PageService - { - get => _navigationService?.GetService(); - set => _navigationService?.SetService(value); - } - - /// - public int PreviousPageIndex => _navigationService?.GetPreviousId() ?? 0; - - /// - public bool CanGoBack => _navigationService is not null && _navigationService.CanGoBack; - - /// - public INavigationItem? Current { get; internal set; } - - /// - /// Static constructor overriding default properties. - /// - static NavigationBase() - { - KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata( - typeof(NavigationBase), - new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained)); - - KeyboardNavigation.TabNavigationProperty.OverrideMetadata( - typeof(NavigationBase), - new FrameworkPropertyMetadata(KeyboardNavigationMode.Once)); - } - - /// - /// Prepares base navigation properties. - /// - protected NavigationBase() - { - Current = (INavigationItem)null; - - // Prepare individual collections for this navigation - Items ??= new ObservableCollection(); - Footer ??= new ObservableCollection(); - - _navigationService = new Wpf.Ui.Services.Internal.NavigationService(); - _navigationService.TransitionDuration = TransitionDuration; - _navigationService.TransitionType = TransitionType; - - if (Frame != null) - _navigationService.SetFrame(Frame); - - // Let the NavigationItem children be able to get me. - NavigationParent = this; - - // Loaded does not have override - Loaded += OnLoaded; - } - - public bool NavigateBack() - { - if (_navigationService is null) return false; - - if (!_navigationService.NavigateBack()) - return false; - - NavigateInternal(0, true); - - return true; - } - - /// - public bool Navigate(Type pageType) - { - return Navigate(pageType, null); - } - - /// - public bool Navigate(Type pageType, object? dataContext) - { - if (!_navigationService.Navigate(pageType, dataContext)) - return false; - - NavigateInternal(0, true); - - return true; - } - - /// - public bool Navigate(string pageTag) - { - return Navigate(pageTag, null); - } - - /// - public bool Navigate(string pageTag, object? dataContext) - { - if (!_navigationService.Navigate(pageTag, dataContext)) - return false; - - NavigateInternal(0, true); - - return true; - } - - - /// - public bool Navigate(int pageId) - { - return Navigate(pageId, null); - } - - /// - public bool Navigate(int pageId, object? dataContext) - { - if (_navigationService != null) - if (!_navigationService.Navigate(pageId, dataContext)) - return false; - - NavigateInternal(-1, true); - - return true; - } - - /// - public bool NavigateExternal(object frameworkElement) - { - return NavigateExternal(frameworkElement, null); - } - - /// - public bool NavigateExternal(object frameworkElement, object? dataContext) - { - if (_navigationService != null) - if (!_navigationService.NavigateExternal(frameworkElement, dataContext)) - return false; - - NavigateInternal(-1, true); - - return true; - } - - /// - public bool NavigateExternal(Uri absolutePageUri) - { - return NavigateExternal(absolutePageUri, null); - } - - /// - public bool NavigateExternal(Uri absolutePageUri, object? dataContext) - { - if (_navigationService != null) - if (!_navigationService.NavigateExternal(absolutePageUri, dataContext)) - return false; - - NavigateInternal(-1, false); - - return true; - } - - /// - public void SetCurrentContext(object dataContext) - { - if (Frame?.Content is not FrameworkElement) - return; - - ((FrameworkElement)Frame.Content).DataContext = dataContext; - - if (dataContext is IViewModel) - ((IViewModel)dataContext).OnMounted(((FrameworkElement)Frame.Content)); - } - - /// - public bool SetContext(string pageTag, object dataContext) - { - if (_navigationService == null) - return false; - - return _navigationService.SetContext(pageTag, dataContext); - } - - /// - public bool SetContext(int pageId, object dataContext) - { - if (_navigationService == null) - return false; - - return _navigationService.SetContext(pageId, dataContext); - } - - /// - public void Flush() - { - Items.Clear(); - Footer.Clear(); - - Current = (INavigationItem)null; - } - - /// - public void ClearCache() - { - if (_navigationService == null) - return; - - _navigationService.ClearCache(); - } - - /// - /// Updates property and modifies Active attribute of navigation items. - /// - private void UpdateItems() - { - var currentTag = _navigationService?.GetCurrentTag() ?? String.Empty; - - foreach (var singleNavigationControl in Items) - { - if (singleNavigationControl is not INavigationItem) - continue; - - if (((INavigationItem)singleNavigationControl).PageTag == currentTag) - { - ((INavigationItem)singleNavigationControl).IsActive = true; - Current = (INavigationItem)singleNavigationControl; - } - else - { - ((INavigationItem)singleNavigationControl).IsActive = false; - } - } - - foreach (var singleNavigationControl in Footer) - { - if (singleNavigationControl is not INavigationItem) - continue; - - if (((INavigationItem)singleNavigationControl).PageTag == currentTag) - { - ((INavigationItem)singleNavigationControl).IsActive = true; - Current = (INavigationItem)singleNavigationControl; - } - else - { - ((INavigationItem)singleNavigationControl).IsActive = false; - } - } - } - - /// - /// This virtual method is called when is loaded. - /// - protected virtual void OnLoaded(object sender, RoutedEventArgs e) - { - UpdateServiceItems(); - - if (PageService == null && Frame != null && SelectedPageIndex > -1) - Navigate(SelectedPageIndex); - - // If we are using the MVVM model, do not use the cache. - if (Precache) - { - if (PageService != null) - throw new InvalidOperationException("The cache cannot be used if you are using IPageService."); - - // TODO: Precache - //await PrecacheInstances(); - } - } - - /// - protected override void OnKeyDown(KeyEventArgs e) - { - // We handle Left/Up/Right/Down keys for keyboard navigation only, - // so no modifiers are needed. - if (Keyboard.Modifiers is not ModifierKeys.None) - return; - - // For most cases, this method do nothing because it does not receive focus by default. - // But if someone set focus to it, the key handling can move the focus to its navigation children. - switch (e.Key) - { - // We use Direction Left/Up/Right/Down instead of Previous/Next to make sure - // that the KeyboardNavigation.DirectionalNavigation property works correctly. - case Key.Left: - MoveFocus(this, FocusNavigationDirection.Left); - e.Handled = true; - break; - - case Key.Up: - MoveFocus(this, FocusNavigationDirection.Up); - e.Handled = true; - break; - - case Key.Right: - MoveFocus(this, FocusNavigationDirection.Right); - e.Handled = true; - break; - - case Key.Down: - MoveFocus(this, FocusNavigationDirection.Down); - e.Handled = true; - break; - } - - if (!e.Handled) - base.OnKeyDown(e); - - static void MoveFocus(FrameworkElement element, FocusNavigationDirection direction) - { - var request = new TraversalRequest(direction); - element.MoveFocus(request); - } - } - - /// - /// This virtual method is called during any navigation and it raises the . - /// - protected virtual void OnNavigated() - { - var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, Current); - RaiseEvent(newEvent); - } - - /// - /// This virtual method is called during forward navigation and it raises the . - /// - protected virtual void OnNavigatedForward() - { - var newEvent = new RoutedNavigationEventArgs(NavigatedForwardEvent, this, Current); - RaiseEvent(newEvent); - } - - /// - /// This virtual method is called during backward navigation and it raises the . - /// - protected virtual void OnNavigatedBackward() - { - var newEvent = new RoutedNavigationEventArgs(NavigatedBackwardEvent, this, Current); - RaiseEvent(newEvent); - } - - /// - /// This virtual method is called when one of the navigation items is clicked. - /// - protected virtual void OnNavigationItemClicked(object sender, RoutedEventArgs e) - { - if (sender is not INavigationItem navigationItem) - return; - - if (navigationItem.AbsolutePageSource == null && navigationItem.PageType == null) - return; - - if (PageService == null) - { - Navigate(navigationItem.PageTag); - - return; - } - - if (navigationItem.PageType == null) - throw new InvalidOperationException("When navigating through the IPageService, the navigated page type must be defined the INavigationItem.PageType."); - - Navigate(navigationItem.PageType); - } - - /// - /// This virtual method is called when something is added, deleted or changed in or . - /// - protected virtual void OnNavigationCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - if (IsLoaded) - UpdateServiceItems(); - - if (e.NewItems != null) - foreach (var addedItem in e.NewItems) - if (addedItem is INavigationItem) - { - ((INavigationItem)addedItem).Click -= OnNavigationItemClicked; // Unsafe - Remove duplicates - ((INavigationItem)addedItem).Click += OnNavigationItemClicked; - } - - if (e.OldItems == null) - return; - - foreach (var deletedItem in e.OldItems) - ((INavigationItem)deletedItem).Click -= OnNavigationItemClicked; - } - - /// - /// Triggered when is changed. - /// - private static void OnItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationBase navigationBase) - return; - - navigationBase.InitializeServiceItems(); - - if (e.NewValue is not ObservableCollection itemsCollection) - return; - - itemsCollection.CollectionChanged += navigationBase.OnNavigationCollectionChanged; - } - - /// - /// Triggered when is changed. - /// - private static void OnFooterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationBase navigationBase) - return; - - navigationBase.InitializeServiceItems(); - - if (e.NewValue is not ObservableCollection itemsCollection) - return; - - itemsCollection.CollectionChanged += navigationBase.OnNavigationCollectionChanged; - } - - /// - /// This virtual method is called when one of the navigation items is clicked. - /// - protected virtual void OnFrameChanged(Frame frame) - { - _navigationService?.SetFrame(frame); - } - - /// - /// Triggered when is changed. - /// - private static void OnFrameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationBase navigationBase || e.NewValue is not Frame frame) - return; - - navigationBase.OnFrameChanged(frame); - } - - private static void OnTransitionDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationBase navigation) - return; - - if (navigation._navigationService == null) - return; - - navigation._navigationService.TransitionDuration = (int)e.NewValue; - } - - private static void OnTransitionTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationBase navigation) - return; - - if (navigation._navigationService == null) - return; - - navigation._navigationService.TransitionType = (Animations.TransitionType)e.NewValue; - } - - /// - /// Gets the parent view for its children. - /// - /// - /// - internal static NavigationBase? GetNavigationParent(T navigationItem) - where T : DependencyObject, INavigationItem - { - return (NavigationBase?)navigationItem.GetValue(NavigationParentProperty); - } - - private void InitializeServiceItems() - { - var navigationItems = GetValue(ItemsProperty) as ObservableCollection ?? new ObservableCollection { }; - var navigationFooter = GetValue(FooterProperty) as ObservableCollection ?? new ObservableCollection { }; - - foreach (var addedItem in navigationItems) - if (addedItem is INavigationItem) - { - ((INavigationItem)addedItem).Click -= OnNavigationItemClicked; // Unsafe - Remove duplicates - ((INavigationItem)addedItem).Click += OnNavigationItemClicked; - } - - foreach (var addedItem in navigationFooter) - if (addedItem is INavigationItem) - { - ((INavigationItem)addedItem).Click -= OnNavigationItemClicked; // Unsafe - Remove duplicates - ((INavigationItem)addedItem).Click += OnNavigationItemClicked; - } - - UpdateServiceItems(); - } - - private void UpdateServiceItems() - { - var navigationItems = GetValue(ItemsProperty) as ObservableCollection ?? new ObservableCollection { }; - var navigationFooter = GetValue(FooterProperty) as ObservableCollection ?? new ObservableCollection { }; - - if (_navigationService != null) - _navigationService.UpdateItems(navigationItems, navigationFooter); - } - - private void NavigateInternal(int arg, bool updateItems) - { - SelectedPageIndex = _navigationService?.GetCurrentId() ?? +arg; - - if (updateItems) - UpdateItems(); - - OnNavigated(); - - if (SelectedPageIndex > (_navigationService?.GetPreviousId() ?? +arg)) - OnNavigatedForward(); - else - OnNavigatedBackward(); - } -} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationHeader.bmp b/src/Wpf.Ui/Controls/Navigation/NavigationHeader.bmp deleted file mode 100644 index 82af3f66e100bb32948f54da0708ac4c647b16db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSy;&^OY76VZTlvq3r_#>4f( zxmd%EZ1rfK0Gfl - /// Property for . - /// - public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), - typeof(string), typeof(NavigationHeader), - new PropertyMetadata(string.Empty)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), - typeof(Common.SymbolRegular), typeof(NavigationHeader), - new PropertyMetadata(Common.SymbolRegular.Empty)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconFilledProperty = DependencyProperty.Register(nameof(IconFilled), - typeof(bool), typeof(NavigationHeader), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconForegroundProperty = DependencyProperty.Register(nameof(IconForeground), - typeof(Brush), typeof(NavigationHeader), new FrameworkPropertyMetadata(SystemColors.ControlTextBrush, - FrameworkPropertyMetadataOptions.Inherits)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register(nameof(IconSize), - typeof(double), typeof(NavigationHeader), new FrameworkPropertyMetadata(13d)); - - /// - /// Text presented in the header element. - /// - [Bindable(true)] - public string Text - { - get => (string)GetValue(TextProperty); - set => SetValue(TextProperty, value); - } - - /// - [Bindable(true), Category("Appearance")] - public Common.SymbolRegular Icon - { - get => (Common.SymbolRegular)GetValue(IconProperty); - set => SetValue(IconProperty, value); - } - - /// - [Bindable(true), Category("Appearance")] - public bool IconFilled - { - get => (bool)GetValue(IconFilledProperty); - set => SetValue(IconFilledProperty, value); - } - - /// - /// Foreground of the . - /// - [Bindable(true), Category("Appearance")] - public Brush IconForeground - { - get => (Brush)GetValue(IconForegroundProperty); - set => SetValue(IconForegroundProperty, value); - } - - /// - /// Font size of the . - /// - [Bindable(true), Category("Appearance")] - public double IconSize - { - get => (double)GetValue(IconSizeProperty); - set => SetValue(IconSizeProperty, value); - } -} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationSeparator.bmp b/src/Wpf.Ui/Controls/Navigation/NavigationSeparator.bmp deleted file mode 100644 index a2d86c5142c01ea5374254a6fbaf71dad05ccd7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSygs2Bp@NC!?t1Jcd@Mn$g; IOQRSV01Imj_W%F@ diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationSeparator.cs b/src/Wpf.Ui/Controls/Navigation/NavigationSeparator.cs deleted file mode 100644 index 3f498c6fe..000000000 --- a/src/Wpf.Ui/Controls/Navigation/NavigationSeparator.cs +++ /dev/null @@ -1,16 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System.ComponentModel; -using System.Drawing; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Controls.Navigation; - -[ToolboxItem(true)] -[ToolboxBitmap(typeof(NavigationSeparator), "NavigationSeparator.bmp")] -public class NavigationSeparator : System.Windows.Controls.Separator, INavigationControl -{ -} diff --git a/src/Wpf.Ui/Controls/NavigationCompact.bmp b/src/Wpf.Ui/Controls/NavigationCompact.bmp deleted file mode 100644 index 930c735ad4874d8c525cdccac8ecfceef3be6ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSy;&^OY76VZTlv%irVIAmBs SwDX -/// Modern navigation styled similar to the Task Manager in Windows 11. -/// -[ToolboxItem(true)] -[ToolboxBitmap(typeof(NavigationCompact), "NavigationCompact.bmp")] -public class NavigationCompact : Wpf.Ui.Controls.Navigation.NavigationBase -{ - /// - /// Property for . - /// - public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register( - nameof(IsExpanded), - typeof(bool), typeof(NavigationCompact), - new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty TemplateButtonCommandProperty = - DependencyProperty.Register(nameof(TemplateButtonCommand), - typeof(Common.IRelayCommand), typeof(NavigationCompact), new PropertyMetadata(null)); - - /// - /// Gets or sets a value indicating whether the menu is expanded. - /// - public bool IsExpanded - { - get => (bool)GetValue(IsExpandedProperty); - set => SetValue(IsExpandedProperty, value); - } - - /// - /// Command triggered after clicking the button. - /// - public Common.IRelayCommand TemplateButtonCommand => (Common.IRelayCommand)GetValue(TemplateButtonCommandProperty); - - /// - /// Creates new instance and sets default . - /// - public NavigationCompact() : base() => - SetValue(TemplateButtonCommandProperty, new Common.RelayCommand(o => Button_OnClick(this, o))); - - private void Button_OnClick(object sender, object parameter) - { - if (parameter == null) - return; - - string param = parameter as string ?? String.Empty; - -#if DEBUG - System.Diagnostics.Debug.WriteLine($"INFO: {typeof(NavigationCompact)} button clicked with param: {param}", "Wpf.Ui.NavigationCompact"); -#endif - if (param == "hamburger") - IsExpanded = !IsExpanded; - } -} diff --git a/src/Wpf.Ui/Controls/NavigationFluent.bmp b/src/Wpf.Ui/Controls/NavigationFluent.bmp deleted file mode 100644 index 930c735ad4874d8c525cdccac8ecfceef3be6ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSy;&^OY76VZTlv%irVIAmBs SwDX -/// Modern navigation styled according to the principles of Fluent Design for Windows 11. -/// -[ToolboxItem(true)] -[ToolboxBitmap(typeof(NavigationFluent), "NavigationFluent.bmp")] -public class NavigationFluent : Wpf.Ui.Controls.Navigation.NavigationBase -{ - // XAML -} diff --git a/src/Wpf.Ui/Controls/NavigationItem.bmp b/src/Wpf.Ui/Controls/NavigationItem.bmp deleted file mode 100644 index 930c735ad4874d8c525cdccac8ecfceef3be6ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSy;&^OY76VZTlv%irVIAmBs SwDX -/// Navigation element. -/// -[ToolboxItem(true)] -[ToolboxBitmap(typeof(NavigationItem), "NavigationItem.bmp")] -public class NavigationItem : System.Windows.Controls.Primitives.ButtonBase, IUriContext, INavigationItem, INavigationControl, IIconControl -{ - /// - /// Property for . - /// - public static readonly DependencyProperty PageTagProperty = DependencyProperty.Register(nameof(PageTag), - typeof(string), typeof(NavigationItem), new PropertyMetadata(String.Empty)); - - /// - /// Property for . - /// - public static readonly DependencyProperty PageSourceProperty = DependencyProperty.Register(nameof(PageSource), - typeof(Uri), typeof(NavigationItem), new PropertyMetadata((Uri)null, OnPageSourceChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty PageTypeProperty = DependencyProperty.Register(nameof(PageType), - typeof(Type), typeof(NavigationItem), new PropertyMetadata((Type)null, OnPageTypeChanged)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(nameof(IsActive), - typeof(bool), typeof(NavigationItem), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty CacheProperty = DependencyProperty.Register(nameof(Cache), - typeof(bool), typeof(NavigationItem), new PropertyMetadata(true)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), - typeof(Common.SymbolRegular), typeof(NavigationItem), - new PropertyMetadata(Common.SymbolRegular.Empty)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register(nameof(IconSize), - typeof(double), typeof(NavigationItem), - new PropertyMetadata(18d)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconFilledProperty = DependencyProperty.Register(nameof(IconFilled), - typeof(bool), typeof(NavigationItem), new PropertyMetadata(false)); - - /// - /// Property for . - /// - public static readonly DependencyProperty IconForegroundProperty = DependencyProperty.Register(nameof(IconForeground), - typeof(Brush), typeof(NavigationItem), new FrameworkPropertyMetadata(SystemColors.ControlTextBrush, - FrameworkPropertyMetadataOptions.Inherits)); - - /// - /// Property for . - /// - public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(nameof(Image), - typeof(BitmapSource), typeof(NavigationItem), - new PropertyMetadata(null)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent ActivatedEvent = EventManager.RegisterRoutedEvent( - nameof(Activated), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NavigationItem)); - - /// - /// Routed event for . - /// - public static readonly RoutedEvent DeactivatedEvent = EventManager.RegisterRoutedEvent( - nameof(Deactivated), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(NavigationItem)); - - /// - public string PageTag - { - get => (string)GetValue(PageTagProperty); - set => SetValue(PageTagProperty, value); - } - - /// - public Uri PageSource - { - get => (Uri)GetValue(PageSourceProperty); - set => SetValue(PageSourceProperty, value); - - } - - /// - public Type PageType - { - get => (Type)GetValue(PageTypeProperty); - set => SetValue(PageTypeProperty, value); - } - - /// - public bool IsActive - { - get => (bool)GetValue(IsActiveProperty); - set - { - if (value == IsActive) - return; - - RaiseEvent(value - ? new RoutedEventArgs(ActivatedEvent, this) - : new RoutedEventArgs(DeactivatedEvent, this)); - - SetValue(IsActiveProperty, value); - } - } - - /// - public bool Cache - { - get => (bool)GetValue(CacheProperty); - set => SetValue(CacheProperty, value); - } - - /// - [Bindable(true), Category("Appearance")] - [Localizability(LocalizationCategory.None)] - public Common.SymbolRegular Icon - { - get => (Common.SymbolRegular)GetValue(IconProperty); - set => SetValue(IconProperty, value); - } - - /// - [Bindable(true), Category("Appearance")] - [Localizability(LocalizationCategory.None)] - public bool IconFilled - { - get => (bool)GetValue(IconFilledProperty); - set => SetValue(IconFilledProperty, value); - } - - /// - /// Size of the . - /// - [TypeConverter(typeof(FontSizeConverter))] - [Bindable(true), Category("Appearance")] - [Localizability(LocalizationCategory.None)] - public double IconSize - { - get => (double)GetValue(IconSizeProperty); - set => SetValue(IconSizeProperty, value); - } - - /// - /// Foreground of the . - /// - [Bindable(true), Category("Appearance")] - public Brush IconForeground - { - get => (Brush)GetValue(IconForegroundProperty); - set => SetValue(IconForegroundProperty, value); - } - - /// - /// Gets or sets image displayed next to the card name instead of the icon. - /// - [Bindable(true), Category("Appearance")] - public BitmapSource Image - { - get => GetValue(ImageProperty) as BitmapSource; - set => SetValue(ImageProperty, value); - } - - /// - /// Occurs when is activated via . - /// - public event RoutedEventHandler Activated - { - add => AddHandler(ActivatedEvent, value); - remove => RemoveHandler(ActivatedEvent, value); - } - - /// - /// Occurs when is deactivated via . - /// - public event RoutedEventHandler Deactivated - { - add => AddHandler(DeactivatedEvent, value); - remove => RemoveHandler(DeactivatedEvent, value); - } - - /// - [Bindable(false)] - public Uri AbsolutePageSource { get; internal set; } - - /// - Uri IUriContext.BaseUri - { - get => BaseUri; - set => BaseUri = value; - } - - /// - /// Implementation for BaseUri. - /// - protected virtual Uri BaseUri - { - get => (Uri)GetValue(BaseUriHelper.BaseUriProperty); - set => SetValue(BaseUriHelper.BaseUriProperty, value); - } - - /// - protected override void OnContentChanged(object oldContent, object newContent) - { - base.OnContentChanged(oldContent, newContent); - - if (newContent is string && String.IsNullOrEmpty(PageTag)) - PageTag = newContent?.ToString()?.ToLower()?.Trim() ?? String.Empty; - } - - /// - protected override void OnKeyDown(KeyEventArgs e) - { - if (Keyboard.Modifiers is not ModifierKeys.None) - { - // We handle Left/Up/Right/Down keys for keyboard navigation only, - // so no modifiers are needed. - return; - } - - switch (e.Key) - { - // We use Direction Left/Up/Right/Down instead of Previous/Next to make sure - // that the KeyboardNavigation.DirectionalNavigation property works correctly. - case Key.Left: - MoveFocus(this, FocusNavigationDirection.Left); - e.Handled = true; - break; - - case Key.Up: - MoveFocus(this, FocusNavigationDirection.Up); - e.Handled = true; - break; - - case Key.Right: - MoveFocus(this, FocusNavigationDirection.Right); - e.Handled = true; - break; - - case Key.Down: - MoveFocus(this, FocusNavigationDirection.Down); - e.Handled = true; - break; - - case Key.Space: - case Key.Enter: - - // Item doesn't define a page, skip navigation. - if (PageSource == null && PageType == null) - break; - - if (NavigationBase.GetNavigationParent(this) is { } navigation - && PageTag is { } pageTag - && !String.IsNullOrEmpty(pageTag)) - { - e.Handled = true; - - navigation.Navigate(pageTag); - } - break; - } - - // If it is simply treated as a button, pass the information about the click on. - if (!e.Handled) - base.OnKeyDown(e); - - static void MoveFocus(FrameworkElement element, FocusNavigationDirection direction) - { - var request = new TraversalRequest(direction); - element.MoveFocus(request); - } - } - - /// - /// This virtual method is called when of the selected page is changed. - /// - protected virtual void OnPageSourceChanged(Uri pageUri) - { - if (!pageUri.OriginalString.EndsWith(".xaml")) - throw new ArgumentException($"URI in {typeof(NavigationItem)} must point to the XAML Page."); - - AbsolutePageSource = ResolvePageUri(pageUri); - } - - private static void OnPageSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationItem navigationItem) - return; - - navigationItem.OnPageSourceChanged(e.NewValue as Uri); - } - - /// - /// This virtual method is called when of the selected page is changed. - /// - protected virtual void OnPageTypeChanged(Type pageType) - { - if (pageType == null) - return; - - if (!typeof(System.Windows.FrameworkElement).IsAssignableFrom(pageType)) - throw new ArgumentException($"{pageType} is not inherited from {typeof(System.Windows.FrameworkElement)}."); - } - - private static void OnPageTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is not NavigationItem navigationItem) - return; - - navigationItem.OnPageTypeChanged(e.NewValue as Type); - } - - /// - /// Tries to resolve absolute path to the Page template. - /// - private Uri ResolvePageUri(Uri pageUri) - { - if (pageUri == null || pageUri.IsAbsoluteUri) - return pageUri; - - if (!pageUri.EndsWith(".xaml")) - throw new ArgumentException("PageSource must point to the .xaml file."); - - var baseUri = BaseUri; - - if (baseUri == null) - { - // TODO: Force extracting BaseUri for Designer - // This is a hackery solution that needs to be refined. - - if (!DesignerHelper.IsInDesignMode) - throw new UriFormatException("Unable to resolve absolute URI for selected page"); - - // The navigation simply prints a blank page during the design process. - PageType = typeof(System.Windows.Controls.Page); - - return null; - } - - if (!baseUri.IsAbsoluteUri) - throw new ApplicationException("Unable to resolve base URI for selected page"); - - if (baseUri.EndsWith(".xaml")) - baseUri = baseUri.TrimLastSegment(); - - return baseUri.Append(pageUri); - } -} diff --git a/src/Wpf.Ui/Controls/NavigationStore.bmp b/src/Wpf.Ui/Controls/NavigationStore.bmp deleted file mode 100644 index 930c735ad4874d8c525cdccac8ecfceef3be6ce0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmZ?rwP0od12Z700mK4O%*Y@C7H0y=3voj*SO7@;XZSy;&^OY76VZTlv%irVIAmBs SwDX -/// Modern navigation styled according to the principles of Fluent Design for Windows 11. -/// -[ToolboxItem(true)] -[ToolboxBitmap(typeof(NavigationStore), "NavigationStore.bmp")] -public class NavigationStore : Wpf.Ui.Controls.Navigation.NavigationBase -{ - // XAML -} diff --git a/src/Wpf.Ui/Controls/NavigationView.cs b/src/Wpf.Ui/Controls/NavigationView.cs deleted file mode 100644 index 855dddee4..000000000 --- a/src/Wpf.Ui/Controls/NavigationView.cs +++ /dev/null @@ -1,70 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System.Windows; -using System.Windows.Controls; -using Wpf.Ui.Common; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Controls; - -/// -/// Ready navigation that includes a control, and . -/// -[TemplatePart(Name = "PART_Navigation", Type = typeof(Wpf.Ui.Controls.Navigation.NavigationBase))] -[TemplatePart(Name = "PART_Breadcrumb", Type = typeof(Wpf.Ui.Controls.Breadcrumb))] -[TemplatePart(Name = "PART_Frame", Type = typeof(System.Windows.Controls.Frame))] -public class NavigationView : System.Windows.Controls.Control -{ - /// - /// Template element represented by the PART_Popup name. - /// - private const string ElementNavigation = "PART_Navigation"; - - /// - /// Template element represented by the PART_Popup name. - /// - private const string ElementBreadcrumb = "PART_Breadcrumb"; - - /// - /// Template element represented by the PART_Popup name. - /// - private const string ElementFrame = "PART_Frame"; - - public static readonly DependencyProperty TypeProperty = DependencyProperty.Register(nameof(Type), - typeof(NavigationType), typeof(NavigationView), - new PropertyMetadata(NavigationType.Compact)); - - /// - /// Navigation control. - /// - public INavigation Navigation { get; protected set; } - - /// - /// Navigation breadcrumb. - /// - public Breadcrumb Breadcrumb { get; protected set; } - - /// - /// Navigation frame - /// - public Frame Frame { get; protected set; } - - public NavigationType Type - { - get => (NavigationType)GetValue(TypeProperty); - set => SetValue(TypeProperty, value); - } - - /// - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - - Navigation = GetTemplateChild(ElementNavigation) as INavigation; - Breadcrumb = GetTemplateChild(ElementBreadcrumb) as Breadcrumb; - Frame = GetTemplateChild(ElementFrame) as Frame; - } -} diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs deleted file mode 100644 index 1914de8c0..000000000 --- a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs +++ /dev/null @@ -1,65 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Windows.Controls; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Mvvm.Contracts; - -/// -/// Represents a contract with a that contains . -/// Through defined service allows you to use the Dependency Injection pattern in WPF UI navigation. -/// -public interface INavigationService -{ - /// - /// Provides direct access to the used in navigation. - /// - /// Instance of the control. - Frame GetFrame(); - - /// - /// Sets the used by . - /// - /// Frame to set. - void SetFrame(Frame frame); - - /// - /// Provides direct access to the control responsible for navigation. - /// - /// Instance of the control. - INavigation GetNavigationControl(); - - /// - /// Lets you attach the control that represents the . - /// - /// Instance of the . - void SetNavigationControl(INavigation navigation); - - /// - /// Lets you attach the service that delivers page instances to . - /// - /// Instance of the with attached service provider. - void SetPageService(IPageService pageService); - - /// - /// Lets you navigate to the selected page based on it's type. Should be used with . - /// - /// of the page. - bool Navigate(Type pageType); - - /// - /// Lets you navigate to the selected page based on it's id. Should be used with . - /// - /// Id of the page. - bool Navigate(int pageId); - - /// - /// Lets you navigate to the selected page based on it's tag. Should be used with . - /// - /// Tag of the page. - bool Navigate(string pageTag); -} diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs deleted file mode 100644 index 6d46035a2..000000000 --- a/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs +++ /dev/null @@ -1,51 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Windows.Controls; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Mvvm.Contracts; - -/// -/// Represents a contract with a that contains . -/// Through defined service allows you to use the MVVM model in WPF UI navigation. -/// -public interface INavigationWindow -{ - /// - /// Provides direct access to the used in navigation. - /// - /// Instance of the control. - Frame GetFrame(); - - /// - /// Provides direct access to the control responsible for navigation. - /// - /// Instance of the control. - INavigation GetNavigation(); - - /// - /// Lets you navigate to the selected page based on it's type. Should be used with . - /// - /// of the page. - bool Navigate(Type pageType); - - /// - /// Lets you attach the service that delivers page instances to . - /// - /// Instance of the with attached service provider. - void SetPageService(IPageService pageService); - - /// - /// Triggers the command to open a window. - /// - void ShowWindow(); - - /// - /// Triggers the command to close a window. - /// - void CloseWindow(); -} diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs deleted file mode 100644 index 4818c102d..000000000 --- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs +++ /dev/null @@ -1,97 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Windows.Controls; -using Wpf.Ui.Controls.Interfaces; -using Wpf.Ui.Mvvm.Contracts; - -namespace Wpf.Ui.Mvvm.Services; - -/// -/// A service that provides methods related to navigation. -/// -public partial class NavigationService : INavigationService -{ - /// - /// Locally attached page service. - /// - private IPageService _pageService; - - /// - /// Control representing navigation. - /// - protected INavigation NavigationControl; - - /// - public Frame GetFrame() - { - return NavigationControl?.Frame; - } - - /// - public void SetFrame(Frame frame) - { - if (NavigationControl == null) - return; - - NavigationControl.Frame = frame; - } - - /// - public INavigation GetNavigationControl() - { - return NavigationControl; - } - - /// - public void SetNavigationControl(INavigation navigation) - { - NavigationControl = navigation; - - if (_pageService != null) - NavigationControl.PageService = _pageService; - } - - /// - public void SetPageService(IPageService pageService) - { - if (NavigationControl == null) - { - _pageService = pageService; - - return; - } - - NavigationControl.PageService = pageService; - } - - /// - public bool Navigate(Type pageType) - { - if (NavigationControl == null) - return false; - - return NavigationControl.Navigate(pageType); - } - - /// - public bool Navigate(int pageId) - { - if (NavigationControl == null) - return false; - - return NavigationControl.Navigate(pageId); - } - - /// - public bool Navigate(string pageTag) - { - if (NavigationControl == null) - return false; - - return NavigationControl.Navigate(pageTag); - } -} diff --git a/src/Wpf.Ui/Services/Internal/NavigationService.cs b/src/Wpf.Ui/Services/Internal/NavigationService.cs deleted file mode 100644 index 2bb01717c..000000000 --- a/src/Wpf.Ui/Services/Internal/NavigationService.cs +++ /dev/null @@ -1,865 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Navigation; -using Wpf.Ui.Animations; -using Wpf.Ui.Common; -using Wpf.Ui.Common.Interfaces; -using Wpf.Ui.Controls.Interfaces; -using Wpf.Ui.Mvvm.Contracts; -using Wpf.Ui.Mvvm.Interfaces; - -namespace Wpf.Ui.Services.Internal; - -// NOTE: -// This class is taped combining many weird tricks -// and workarounds. Please don't judge me, -// I'm just a student with a bit of free time - -/// -/// Internal navigation service. -/// -internal sealed class NavigationService : IDisposable -{ - #region Private properties - - /// - /// Whether the current class is disposed. - /// - private bool _disposed = false; - - /// - /// Currently navigated page index. - /// - private int _currentPageIndex = -1; - - /// - /// Previously navigated page index. - /// - private int _previousPageIndex = -1; - - /// - /// Current frame. - /// - private Frame? _frame; - - /// - /// MVVM page service. - /// - private IPageService? _pageService; - - /// - /// Current . - /// - private long _currentActionIdentifier { get; set; } - - /// - /// Identifies current Frame process. - /// - private readonly EventIdentifier _eventIdentifier; - - /// - /// 's mirror with cached page contents. - /// - private NavigationServiceItem[] _navigationServiceItems; - - /// - /// - /// - private readonly List _history; - - private bool _isBackNavigated; - - #endregion Private properties - - #region Public properties - - /// - /// Whether to precache instances after rebuilding. - /// - public bool Precache { get; set; } = false; - - /// - /// Transition duration. - /// - public int TransitionDuration { get; set; } - - /// - /// Transition type. - /// - public TransitionType TransitionType { get; set; } - - /// - /// Indicates the possibility of navigation back - /// - public bool CanGoBack => _history.Count > 1; - - #endregion Public properties - - #region Constructors - - /// - /// Creates new instance and prepares internal properties. - /// - public NavigationService() - { - _eventIdentifier = new EventIdentifier(); - _navigationServiceItems = new NavigationServiceItem[] { }; - _history = new List(); - } - - /// - /// Control finalizer. - /// - ~NavigationService() - { - Dispose(false); - } - - #endregion Constructors - - #region Public methods - - public bool NavigateBack() - { - if (_history.Count <= 1) - return false; - - _isBackNavigated = true; - - return NavigateInternal(_history[_history.Count - 2], null!); - } - - /// - /// Navigates the based on provided item Id. - /// - /// Id of the selected page. - /// Additional . - /// - public bool Navigate(int pageId, object dataContext) - { - return NavigateInternal(pageId, dataContext); - } - - /// - /// Navigates the based on provided item . - /// - /// of the selected page. - /// Additional . - /// - public bool Navigate(Type pageType, object dataContext) - { - var selectedIndex = -1; - - for (var i = 0; i < _navigationServiceItems.Length; i++) - { - if (_navigationServiceItems[i].Type != pageType) - continue; - - selectedIndex = i; - - break; - } - - if (selectedIndex >= 0) - return NavigateInternal(selectedIndex, dataContext); - - if (_pageService == null) - return false; - - var servicePageInstance = _pageService.GetPage(pageType); - - if (servicePageInstance == null) - throw new InvalidOperationException($"The {pageType} has not been registered in the {typeof(IPageService)} service."); - - _previousPageIndex = _currentPageIndex; - _currentPageIndex = -1; - - _currentActionIdentifier = _eventIdentifier.GetNext(); - - _frame?.Navigate(servicePageInstance); - - return true; - } - - /// - /// Navigates the based on provided item tag. - /// - /// Tag of the page. - /// Additional . - /// - public bool Navigate(string pageTag, object dataContext) - { - var selectedIndex = -1; - - for (var i = 0; i < _navigationServiceItems.Length; i++) - { - if (_navigationServiceItems[i].Tag != pageTag) - continue; - - selectedIndex = i; - - break; - } - - if (selectedIndex < 0) - return false; - - return NavigateInternal(selectedIndex, dataContext); - } - - /// - /// Navigates statically outside of the current navigation scope. - /// - /// to navigate. - /// Additional . - public bool NavigateExternal(object frameworkElement, object dataContext) - { - if (_frame == null) - return false; - - if (frameworkElement is not FrameworkElement) - throw new InvalidOperationException($"Only class derived {typeof(FrameworkElement)} can be used for navigation."); - - _previousPageIndex = _currentPageIndex; - _currentPageIndex = -1; - - _currentActionIdentifier = _eventIdentifier.GetNext(); - - _frame.Navigate( - frameworkElement, - new NavigationServiceExtraData - { - PageId = -1, - Cache = false, - DataContext = dataContext - }); - - return true; - } - - /// - /// Navigates statically outside of the current navigation scope. - /// - /// Uri of the to navigate. - /// Additional . - public bool NavigateExternal(Uri frameworkElementUri, object dataContext) - { - if (_frame == null) - return false; - - if (!frameworkElementUri.IsAbsoluteUri) - throw new InvalidOperationException($"Navigation Uri must be absolute Uri pointing to an element derived from {typeof(FrameworkElement)}."); - - _previousPageIndex = _currentPageIndex; - _currentPageIndex = -1; - - _currentActionIdentifier = _eventIdentifier.GetNext(); - - _frame.Navigate( - frameworkElementUri, - new NavigationServiceExtraData - { - PageId = -1, - Cache = false, - DataContext = dataContext - }); - - return true; - } - - /// - /// Sets DataContext for the selected instance. - /// - /// Tag of the page. - /// Context to set. - public bool SetContext(string pageTag, object dataContext) - { - for (var i = 0; i < _navigationServiceItems.Length; i++) - { - if (_navigationServiceItems[i].Tag != pageTag) - continue; - - if (_navigationServiceItems[i].Instance is not FrameworkElement) - return false; - - ((FrameworkElement)_navigationServiceItems[i].Instance).DataContext = dataContext; - - return true; - } - - return false; - } - - /// - /// Sets DataContext for the selected instance. - /// - /// Selected page Id. - /// Context to set. - public bool SetContext(int serviceItemId, object dataContext) - { - if (_navigationServiceItems.Length - 1 < serviceItemId) - return false; - - if (_navigationServiceItems[serviceItemId].Instance is not FrameworkElement) - return false; - - ((FrameworkElement)_navigationServiceItems[serviceItemId].Instance).DataContext = dataContext; - - return true; - } - - /// - /// Creates mirror of based on provided collection of 's. - /// - public void UpdateItems(IEnumerable? mainItems, IEnumerable? additionalItems) - { - var serviceItemCollection = new List { }; - - if (mainItems != null) - foreach (var singleNavigationControl in mainItems) - { - if (singleNavigationControl is not INavigationItem navigationItem) - continue; - - serviceItemCollection.Add(NavigationServiceItem.Create(navigationItem)); - } - - if (additionalItems != null) - foreach (var singleNavigationControl in additionalItems) - { - if (singleNavigationControl is not INavigationItem navigationItem) - continue; - - serviceItemCollection.Add(NavigationServiceItem.Create(navigationItem)); - } - - _navigationServiceItems = serviceItemCollection.ToArray(); - - // Should we precache here? It can be intensive cause the update can be fired multiple times during initialization - //if (Precache) - //{ - //} - } - - /// - /// Clears cache stored inside service items. - /// - public void ClearCache() - { - foreach (var singleServiceItem in _navigationServiceItems) - singleServiceItem.Instance = null; - } - - /// - /// Sets currently used . - /// - /// Frame to set. - public void SetFrame(Frame frame) - { - if (frame == null) - return; - - _frame = frame; - - _frame.NavigationUIVisibility = NavigationUIVisibility.Hidden; - - _frame.Navigating -= OnFrameNavigating; // Unsafe, but doubling can be catastrophic - _frame.Navigating += OnFrameNavigating; - - _frame.Navigated -= OnFrameNavigated; // Unsafe, but doubling can be catastrophic - _frame.Navigated += OnFrameNavigated; - } - - /// - /// Sets currently used . - /// - /// Service to set. - public void SetService(IPageService pageService) - { - _pageService = pageService; - } - - /// - /// Gets currently used . - /// - public IPageService? GetService() - { - return _pageService ?? null; - } - - /// - /// Gets currently displayed item tag. - /// - public string GetCurrentTag() - { - if (_currentPageIndex < 0) - return "__external__"; - - if (_navigationServiceItems.Length == 0) - return string.Empty; - - if (_navigationServiceItems.Length - 1 < _currentPageIndex) - return string.Empty; - - return _navigationServiceItems[_currentPageIndex].Tag; - } - - /// - /// Currently displayed page Id. - /// - public int GetCurrentId() - { - return _currentPageIndex; - } - - /// - /// Previously displayed page Id. - /// - public int GetPreviousId() - { - return _previousPageIndex; - } - - #endregion Public methods - - #region Disposing - - /// - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - /// - /// If disposing equals , the method has been called directly or indirectly - /// by a user's code. Managed and unmanaged resources can be disposed. If disposing equals , - /// the method has been called by the runtime from inside the finalizer and you should not - /// reference other objects. - /// Only unmanaged resources can be disposed. - /// - /// If disposing equals , dispose all managed and unmanaged resources. - private void Dispose(bool disposing) - { - if (_disposed) - return; - - _disposed = true; - - if (!disposing) - return; - -#if DEBUG - System.Diagnostics.Debug.WriteLine($"INFO | {typeof(NavigationService)} disposed.", "Wpf.Ui.Navigation"); -#endif - - _navigationServiceItems = null; - } - - #endregion Disposing - - #region Internal navigation - - /// - /// Navigates internally depending on current state of the service. - /// - /// Id of the item to navigate. - /// Additional . - /// - private bool NavigateInternal(int serviceItemId, object dataContext) - { - if (!_navigationServiceItems.Any()) - return false; - - _currentActionIdentifier = _eventIdentifier.GetNext(); - - if (_navigationServiceItems.Length - 1 < serviceItemId) - return false; - - // The navigation item is the same, skip the navigation - if (_currentPageIndex == serviceItemId) - return false; - - // An empty navigation item may be just a button, but as navigation fails, so return false. - if (_navigationServiceItems[serviceItemId].Type == null && - _navigationServiceItems[serviceItemId].Source == null) - return false; - - _previousPageIndex = _currentPageIndex; - _currentPageIndex = serviceItemId; - - if (_pageService != null) - return NavigateInternalByService(serviceItemId); - - - if (!_navigationServiceItems[serviceItemId].Cache) - return NavigateInternalByItemWithoutCache(serviceItemId, dataContext); - - return NavigateInternalByItemWithCache(serviceItemId, dataContext); - } - - /// - /// Navigates internally without service and with enabled cache. - /// - private bool NavigateInternalByItemWithCache(int serviceItemId, object dataContext) - { - if (_frame == null) - return false; - - if (_navigationServiceItems.Length - 1 < serviceItemId) - return false; - - // Navigate internally, with cache enabled, instance does exist so reuse it - if (_navigationServiceItems[serviceItemId].Instance != null) - { - // Sometimes a user may want to update the context of a page that is already in the cache. - if (dataContext != null && _navigationServiceItems[serviceItemId].Instance is FrameworkElement) - ((FrameworkElement)_navigationServiceItems[serviceItemId].Instance).DataContext = dataContext; - - _frame.Navigate( - _navigationServiceItems[serviceItemId].Instance, - new NavigationServiceExtraData - { - PageId = serviceItemId, - Cache = true, - DataContext = dataContext - }); - -#if DEBUG - System.Diagnostics.Debug.WriteLine( - $"DEBUG | {_navigationServiceItems[serviceItemId].Tag} navigated internally, with cache by it's instance."); -#endif - AddToHistory(serviceItemId); - return true; - } - - // Navigate internally, with cache enabled, instance does not exist so create it using type - if (_navigationServiceItems[serviceItemId].Type != null) - { - _navigationServiceItems[serviceItemId].Instance = CreateFrameworkElementInstance(_navigationServiceItems[serviceItemId].Type, dataContext); - - _frame.Navigate( - _navigationServiceItems[serviceItemId].Instance, - new NavigationServiceExtraData - { - PageId = serviceItemId, - Cache = true, - DataContext = null // DataContext used - }); - -#if DEBUG - System.Diagnostics.Debug.WriteLine( - $"DEBUG | {_navigationServiceItems[serviceItemId].Tag} navigated internally, with cache by it's type."); -#endif - AddToHistory(serviceItemId); - return true; - } - - // Navigate internally, with cache enabled, instance does not exist so create it using source - if (_navigationServiceItems[serviceItemId].Source != null) - { - _frame.Navigate( - _navigationServiceItems[serviceItemId].Source, - new NavigationServiceExtraData - { - PageId = serviceItemId, - Cache = true, - DataContext = dataContext - }); - -#if DEBUG - System.Diagnostics.Debug.WriteLine( - $"DEBUG | {_navigationServiceItems[serviceItemId].Tag} navigated internally, with cache by it's source."); -#endif - - AddToHistory(serviceItemId); - return true; - } - - return false; - } - - /// - /// Navigates internally without service and with cache disabled. - /// - private bool NavigateInternalByItemWithoutCache(int serviceItemId, object dataContext) - { - if (_frame == null) - return false; - - if (_navigationServiceItems.Length - 1 < serviceItemId) - return false; - - // Navigate internally, without cache, based on type - if (_navigationServiceItems[serviceItemId].Type != null) - { - _frame.Navigate( - CreateFrameworkElementInstance - ( - _navigationServiceItems[serviceItemId].Type, - dataContext - ), - new NavigationServiceExtraData - { - PageId = serviceItemId, - Cache = false, - DataContext = null // DataContext set above by activator - }); -#if DEBUG - System.Diagnostics.Debug.WriteLine( - $"DEBUG | {_navigationServiceItems[serviceItemId].Tag} navigated internally, without cache by it's type."); -#endif - AddToHistory(serviceItemId); - return true; - } - - if (_navigationServiceItems[serviceItemId].Source != null) - { - _frame.Navigate( - _navigationServiceItems[serviceItemId].Source, - new NavigationServiceExtraData - { - PageId = serviceItemId, - Cache = false, - DataContext = dataContext - }); - -#if DEBUG - System.Diagnostics.Debug.WriteLine( - $"DEBUG | {_navigationServiceItems[serviceItemId].Tag} navigated internally, without cache by it's source."); -#endif - - AddToHistory(serviceItemId); - return true; - } - - // Wait... this should not happen... - return false; - } - - private bool NavigateInternalByService(int serviceItemId) - { - if (_frame == null) - return false; - - if (_navigationServiceItems.Length - 1 < serviceItemId) - return false; - - var servicePageInstance = _pageService.GetPage(_navigationServiceItems[serviceItemId].Type); - - if (servicePageInstance == null) - throw new InvalidOperationException($"The {_navigationServiceItems[serviceItemId].Type} has not been registered in the {typeof(IPageService)} service."); - - _frame.Navigate(servicePageInstance); - AddToHistory(serviceItemId); - - return true; - } - - private void AddToHistory(int serviceItemId) - { - if (_isBackNavigated) - { - _isBackNavigated = false; - _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 2])); - _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 1])); - } - - _history.Add(serviceItemId); - } - - #endregion Internal navigation - - #region Instance management - - /// - /// Tries to create an instance from the selected page type. - /// - private FrameworkElement CreateFrameworkElementInstance(Type pageType, object dataContext) - { - return NavigationServiceActivator.CreateInstance(pageType, dataContext); - } - - #endregion Instance management - - #region Frame events - - /// - /// Event triggered when the frame has already loaded the view, if the page uses the Cache, Content of the Frame should be saved. - /// - private void OnFrameNavigated(object sender, NavigationEventArgs e) - { - if (_frame == null) - return; - - if (_frame.CanGoBack) - _frame.RemoveBackEntry(); - - if (_frame.NavigationService.CanGoBack) - _frame.NavigationService?.RemoveBackEntry(); - - if (TransitionDuration > 0 && e.Content != null) - Transitions.ApplyTransition(e.Content, TransitionType, TransitionDuration); - - // If we are using the MVVM model, - // do not perform internal operations on DataContext and Instances. - if (_pageService != null) - { - // Instance and datacontext determined by the service, notify and leave - NotifyFrameContentAboutEnter(); - - return; - } - - if (e.ExtraData is not NavigationServiceExtraData extraData) - { - // Instance determined by the frame, context not provided, notify and leave - NotifyFrameContentAboutEnter(); - - return; - } - - if (!_currentActionIdentifier.Equals(_currentActionIdentifier)) - { - // Only god knows what's broken, but notify anyway and then leave. - NotifyFrameContentAboutEnter(); - - return; - } - - // DataContext provided by the frame extra data, set. - if (extraData.DataContext != null && _frame.Content is FrameworkElement) - { - ((FrameworkElement)_frame.Content).DataContext = extraData.DataContext; - - if (extraData.DataContext is IViewModel) - ((IViewModel)extraData.DataContext).OnMounted((FrameworkElement)_frame.Content); - } - - if (!extraData.Cache) - { - // Instance determined by the frame, context set from extra data, but without cache, notify and leave - NotifyFrameContentAboutEnter(); - - return; - } - - // We make sure that pageId exists, if it is wrong, the fault lies earlier. - if (_navigationServiceItems.Length - 1 < extraData.PageId || extraData.PageId < 0) - { - // Only god knows what's broken, but notify anyway and then leave. - NotifyFrameContentAboutEnter(); - - return; - } - - // If an instance already exists, do not overwrite it. - if (_navigationServiceItems[extraData.PageId].Instance != null) - { - // Instance determined by the frame, context set from extra data, with cache, but instance cached, notify and leave - NotifyFrameContentAboutEnter(); - - return; - } - - // Finally, the navigation took place internally, - // the context was set from extra data, the cache has to be saved, - // so we save it, notify it and this is the end of the method - _navigationServiceItems[extraData.PageId].Instance = _frame.Content; - - NotifyFrameContentAboutEnter(); - } - - /// - /// Event fired when Frame received a request to navigate. - /// - private void OnFrameNavigating(object sender, NavigatingCancelEventArgs e) - { - if (_frame == null) - return; - - NotifyFrameContentAboutLeave(); - - switch (e.NavigationMode) - { - case NavigationMode.Back: - e.Cancel = true; - - if (_currentPageIndex > 0) - Navigate(_currentPageIndex - 1, null); - break; - - case NavigationMode.Forward: - e.Cancel = true; - - if (_currentPageIndex < _navigationServiceItems.Length - 1) - Navigate(_currentPageIndex + 1, null); - break; - } - } - - /// - /// Notifies content about being navigated. - /// - private void NotifyFrameContentAboutEnter() - { - if (_frame == null) - return; - - if (_frame.Content is INavigationAware) - ((INavigationAware)_frame.Content).OnNavigatedTo(); - - if (_frame.Content is INavigableView navigableView && navigableView.ViewModel is INavigationAware) - ((INavigationAware)navigableView.ViewModel).OnNavigatedTo(); - - if (_frame.Content is FrameworkElement && ((FrameworkElement)_frame.Content).DataContext is INavigationAware) - ((INavigationAware)((FrameworkElement)_frame.Content).DataContext).OnNavigatedTo(); - } - - /// - /// Notifies content about leaving the navigation context. - /// - private void NotifyFrameContentAboutLeave() - { - if (_frame == null) - return; - - if (_frame.Content is INavigationAware) - ((INavigationAware)_frame.Content).OnNavigatedFrom(); - - if (_frame.Content is INavigableView navigableView && navigableView.ViewModel is INavigationAware) - ((INavigationAware)navigableView.ViewModel).OnNavigatedFrom(); - - if (_frame.Content is FrameworkElement && ((FrameworkElement)_frame.Content).DataContext is INavigationAware) - ((INavigationAware)((FrameworkElement)_frame.Content).DataContext).OnNavigatedFrom(); - } - - #endregion Frame events - - #region Preache - - /// - /// Precaches instances of the navigation items. - /// - private void PrecacheItems() - { - if (DesignerHelper.IsInDesignMode) - return; - - if (_pageService != null) - return; - } - - #endregion -} diff --git a/src/Wpf.Ui/Services/Internal/NavigationServiceActivator.cs b/src/Wpf.Ui/Services/Internal/NavigationServiceActivator.cs deleted file mode 100644 index 3bc46b9da..000000000 --- a/src/Wpf.Ui/Services/Internal/NavigationServiceActivator.cs +++ /dev/null @@ -1,166 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Reflection; -using Wpf.Ui.Common; -using Wpf.Ui.Controls; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Services.Internal; - -/// -/// Internal activator for navigation purposes. -/// -internal static class NavigationServiceActivator -{ - /// - /// Creates new instance of type derived from . - /// - /// to instantiate. - /// Instance of the object or . - public static FrameworkElement CreateInstance(Type pageType) - { - return CreateInstance(pageType, null); - } - - /// - /// Creates new instance of type derived from . - /// - /// to instantiate. - /// Additional context to set. - /// Instance of the object or . - public static FrameworkElement CreateInstance(Type pageType, object dataContext) - { - if (!typeof(FrameworkElement).IsAssignableFrom(pageType)) - throw new InvalidCastException( - $"PageType of the ${typeof(INavigationItem)} must be derived from {typeof(FrameworkElement)}. {pageType} is not."); - - if (DesignerHelper.IsInDesignMode) - return new Page { Content = new TextBlock { Text = "Pages are not rendered while using the Designer. Edit the page template directly." } }; - - var instance = null as FrameworkElement; - -#if NET48_OR_GREATER || NETCOREAPP3_0_OR_GREATER - if (ControlsServices.ControlsServiceProvider != null) - { - var pageConstructors = pageType.GetConstructors(); - var parameterlessCount = pageConstructors.Count(ctor => ctor.GetParameters().Length == 0); - var parameterfullCount = pageConstructors.Length - parameterlessCount; - - if (parameterlessCount == 1) - { - instance = InvokeParameterlessConstructor(pageType); - } - else if (parameterlessCount == 0 && parameterfullCount > 0) - { - var selectedCtor = FitBestConstructor(pageConstructors, dataContext); - if (selectedCtor == null) - throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor or the required services have not been configured for dependency injection. Use the static {nameof(ControlsServices)} class to initialize the GUI library with your service provider. If you are using {typeof(Mvvm.Contracts.IPageService)} do not navigate initially and don't use Cache or Precache."); - - instance = InvokeElementConstructor(selectedCtor, dataContext); - SetDataContext(instance, dataContext); - return instance; - } - } - else if (dataContext != null) -#else - if (dataContext != null) -#endif - { - instance = InvokeElementConstructor(pageType, dataContext); - if (instance != null) - return instance; - } - - var emptyConstructor = FindParameterlessConstructor(pageType); - if (emptyConstructor == null) - throw new InvalidOperationException($"The {pageType} page does not have a parameterless constructor. If you are using {typeof(Mvvm.Contracts.IPageService)} do not navigate initially and don't use Cache or Precache."); - - instance = emptyConstructor.Invoke(null) as FrameworkElement; - SetDataContext(instance, dataContext); - return instance; - } - -#if NET48_OR_GREATER || NETCOREAPP3_0_OR_GREATER - private static object ResolveConstructorParameter(Type tParam, object dataContext) - { - if (dataContext != null && dataContext.GetType() == tParam) - { - return dataContext; - } - - return ControlsServices.ControlsServiceProvider.GetService(tParam); - } - - /// - /// Picks a constructor which has the most satisfiable arguments count. - /// - /// - /// - /// - private static ConstructorInfo FitBestConstructor(ConstructorInfo[] parameterfullCtors, object dataContext) - { - return parameterfullCtors.Select(ctor => - { - var parameters = ctor.GetParameters(); - var argumentResolution = parameters.Select(prm => - { - var resolved = ResolveConstructorParameter(prm.ParameterType, dataContext); - return resolved != null; - }); - var fullyResolved = argumentResolution.All(resolved => resolved == true); - var score = fullyResolved ? parameters.Length : 0; - - return score == 0 ? null : new - { - Constructor = ctor, - Score = score - }; - }) - .Where(cs => cs != null) - .OrderBy(cs => cs.Score) - .FirstOrDefault()?.Constructor; - } - - private static FrameworkElement InvokeElementConstructor(ConstructorInfo ctor, object dataContext) - { - var args = ctor - .GetParameters() - .Select(prm => - ResolveConstructorParameter(prm.ParameterType, dataContext)); - - return ctor.Invoke(args.ToArray()) as FrameworkElement; - } -#endif - - private static FrameworkElement InvokeElementConstructor(Type tPage, object dataContext) - { - var ctor = tPage.GetConstructor(new[] { dataContext.GetType() }); - if (ctor != null) - return ctor.Invoke(new[] { dataContext }) as FrameworkElement; - - return null; - } - - private static ConstructorInfo FindParameterlessConstructor(Type tPage) - { - return tPage.GetConstructor(Type.EmptyTypes); - } - - private static FrameworkElement InvokeParameterlessConstructor(Type tPage) - { - return FindParameterlessConstructor(tPage)?.Invoke(null) as FrameworkElement; - } - - private static void SetDataContext(FrameworkElement element, object dataContext) - { - if (dataContext != null) - element.DataContext = dataContext; - } -} diff --git a/src/Wpf.Ui/Services/Internal/NavigationServiceExtraData.cs b/src/Wpf.Ui/Services/Internal/NavigationServiceExtraData.cs deleted file mode 100644 index 0f5892b75..000000000 --- a/src/Wpf.Ui/Services/Internal/NavigationServiceExtraData.cs +++ /dev/null @@ -1,27 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -namespace Wpf.Ui.Services.Internal; - -/// -/// Additional data passed through the method. -/// -internal struct NavigationServiceExtraData -{ - /// - /// Current page id. - /// - public int PageId { get; set; } - - /// - /// Whether we should use the cache. - /// - public bool Cache { get; set; } - - /// - /// Additional . - /// - public object DataContext { get; set; } -} diff --git a/src/Wpf.Ui/Services/Internal/NavigationServiceItem.cs b/src/Wpf.Ui/Services/Internal/NavigationServiceItem.cs deleted file mode 100644 index 7c1377cda..000000000 --- a/src/Wpf.Ui/Services/Internal/NavigationServiceItem.cs +++ /dev/null @@ -1,71 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -using System; -using System.Windows; -using Wpf.Ui.Controls.Interfaces; - -namespace Wpf.Ui.Services.Internal; - -/// -/// Represents in internal methods. -/// -internal class NavigationServiceItem -{ - /// - /// Tags of the presented page. - /// - public string Tag { get; set; } = string.Empty; - - /// - /// Whether the cache is active. - /// - public bool Cache { get; set; } = false; - - /// - /// Type of the . - /// - public Type Type { get; set; } = null; - - /// - /// Source of the . - /// - public Uri Source { get; set; } = null; - - /// - /// Instantiated page content. - /// - public object Instance { get; set; } = null; - - /// - /// Sets DataContext of the . - /// - public bool SetContext(object dataContext) - { - if (!Cache) - return false; - - if (Instance is not FrameworkElement) - return false; - - ((FrameworkElement)Instance).DataContext = dataContext; - - return true; - } - - /// - /// Creates from . - /// - public static NavigationServiceItem Create(INavigationItem navigationItem) - { - return new NavigationServiceItem - { - Tag = navigationItem.PageTag, - Type = navigationItem.PageType, - Source = navigationItem.AbsolutePageSource, - Cache = navigationItem.Cache - }; - } -} diff --git a/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml b/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml deleted file mode 100644 index df9936ef6..000000000 --- a/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/Navigation.xaml b/src/Wpf.Ui/Styles/Controls/Navigation.xaml deleted file mode 100644 index 19161ffe3..000000000 --- a/src/Wpf.Ui/Styles/Controls/Navigation.xaml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Wpf.Ui/Styles/Controls/NavigationBackButton.xaml b/src/Wpf.Ui/Styles/Controls/NavigationBackButton.xaml deleted file mode 100644 index 772909d50..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationBackButton.xaml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Wpf.Ui/Styles/Controls/NavigationCompact.xaml b/src/Wpf.Ui/Styles/Controls/NavigationCompact.xaml deleted file mode 100644 index 9f25a1c0e..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationCompact.xaml +++ /dev/null @@ -1,408 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/NavigationFluent.xaml b/src/Wpf.Ui/Styles/Controls/NavigationFluent.xaml deleted file mode 100644 index 2105adc07..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationFluent.xaml +++ /dev/null @@ -1,316 +0,0 @@ - - - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/NavigationHeader.xaml b/src/Wpf.Ui/Styles/Controls/NavigationHeader.xaml deleted file mode 100644 index 099b19c15..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationHeader.xaml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/NavigationSeparator.xaml b/src/Wpf.Ui/Styles/Controls/NavigationSeparator.xaml deleted file mode 100644 index 0e718b444..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationSeparator.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/NavigationStore.xaml b/src/Wpf.Ui/Styles/Controls/NavigationStore.xaml deleted file mode 100644 index d3c3e85b5..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationStore.xaml +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - - diff --git a/src/Wpf.Ui/Styles/Controls/NavigationView.xaml b/src/Wpf.Ui/Styles/Controls/NavigationView.xaml deleted file mode 100644 index 7453eb9a9..000000000 --- a/src/Wpf.Ui/Styles/Controls/NavigationView.xaml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Wpf.Ui/Styles/Wpf.Ui.xaml b/src/Wpf.Ui/Styles/Wpf.Ui.xaml index f1258ed10..0db00317c 100644 --- a/src/Wpf.Ui/Styles/Wpf.Ui.xaml +++ b/src/Wpf.Ui/Styles/Wpf.Ui.xaml @@ -24,15 +24,6 @@ - - - - - - - - - diff --git a/src/Wpf.Ui/Wpf.Ui.csproj b/src/Wpf.Ui/Wpf.Ui.csproj index c30de4143..bd378cc9c 100644 --- a/src/Wpf.Ui/Wpf.Ui.csproj +++ b/src/Wpf.Ui/Wpf.Ui.csproj @@ -91,12 +91,8 @@ - - - - @@ -126,12 +122,6 @@ - - - - - - From 9d23ce5c4f0f03d8000aba0a23d77b692a5830ab Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 22:17:04 +0200 Subject: [PATCH 04/38] Add visual style for NavigationView --- .../Controls/Interfaces/INavigationView.cs | 5 ++++ .../Navigation/NavigationView.Properties.cs | 14 ++++++++++ .../Navigation/NavigationViewVisualStyle.cs | 27 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs index d7209edd5..5cef3d68a 100644 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs @@ -62,6 +62,11 @@ public interface INavigationView /// bool IsPaneVisible { get; set; } + /// + /// Determines the visual style of the NavigationView. + /// + NavigationViewVisualStyle VisualStyle { get; set; } + /// /// Occurs when the NavigationView pane is opened. /// diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs index e551a5d0d..56bcc97be 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs @@ -76,6 +76,13 @@ public partial class NavigationView typeof(bool), typeof(NavigationView), new FrameworkPropertyMetadata(false)); + /// + /// Property for . + /// + public static readonly DependencyProperty VisualStyleProperty = DependencyProperty.Register(nameof(VisualStyle), + typeof(NavigationViewVisualStyle), typeof(NavigationView), + new FrameworkPropertyMetadata(NavigationViewVisualStyle.Compact)); + /// public IList MenuItems { @@ -138,4 +145,11 @@ public bool IsPaneVisible get => (bool)GetValue(IsPaneVisibleProperty); set => SetValue(IsPaneVisibleProperty, value); } + + /// + public NavigationViewVisualStyle VisualStyle + { + get => (NavigationViewVisualStyle)GetValue(VisualStyleProperty); + set => SetValue(VisualStyleProperty, value); + } } diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs new file mode 100644 index 000000000..6cc0e56dc --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs @@ -0,0 +1,27 @@ +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +/// +/// Defines constants that specify visual style of the NavigationView. +/// +public enum NavigationViewVisualStyle +{ + /// + /// Standard visual style of NavigationView in Win Ui. + /// + Compact, + + /// + /// Wide buttons, with full titles, similar to the settings app for Windows 11. + /// + Wide, + + /// + /// Modern, tiled style of navigation, similar to the Windows Store app. + /// + Fluent, +} From 71fcf8d303391ed4e434adfcfadb244da8ce21df Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 22:23:47 +0200 Subject: [PATCH 05/38] Add PaneLength and Header property to NavigationView --- .../Controls/Interfaces/INavigationView.cs | 10 +++++++ .../Navigation/NavigationView.Properties.cs | 28 +++++++++++++++++++ .../Navigation/NavigationViewVisualStyle.cs | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs index 5cef3d68a..6e8c84759 100644 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs @@ -16,6 +16,11 @@ namespace Wpf.Ui.Controls.Interfaces; /// public interface INavigationView { + /// + /// Gets or sets the header content. + /// + object Header { get; set; } + /// /// Gets the collection of menu items displayed in the NavigationView. /// @@ -62,6 +67,11 @@ public interface INavigationView /// bool IsPaneVisible { get; set; } + /// + /// Gets or sets the width of the NavigationView pane when it's fully expanded. + /// + double OpenPaneLength { get; set; } + /// /// Determines the visual style of the NavigationView. /// diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs index 56bcc97be..9ba626e86 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs @@ -13,6 +13,13 @@ namespace Wpf.Ui.Controls.Navigation; public partial class NavigationView { + /// + /// Property for . + /// + public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(nameof(Header), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + /// /// Property for . /// @@ -76,6 +83,13 @@ public partial class NavigationView typeof(bool), typeof(NavigationView), new FrameworkPropertyMetadata(false)); + /// + /// Property for . + /// + public static readonly DependencyProperty OpenPaneLengthProperty = DependencyProperty.Register(nameof(OpenPaneLength), + typeof(double), typeof(NavigationView), + new FrameworkPropertyMetadata(0D)); + /// /// Property for . /// @@ -83,6 +97,13 @@ public partial class NavigationView typeof(NavigationViewVisualStyle), typeof(NavigationView), new FrameworkPropertyMetadata(NavigationViewVisualStyle.Compact)); + /// + public object Header + { + get => GetValue(HeaderProperty); + set => SetValue(HeaderProperty, value); + } + /// public IList MenuItems { @@ -146,6 +167,13 @@ public bool IsPaneVisible set => SetValue(IsPaneVisibleProperty, value); } + /// + public double OpenPaneLength + { + get => (double)GetValue(OpenPaneLengthProperty); + set => SetValue(OpenPaneLengthProperty, value); + } + /// public NavigationViewVisualStyle VisualStyle { diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs index 6cc0e56dc..6bff2eef4 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs @@ -11,7 +11,7 @@ namespace Wpf.Ui.Controls.Navigation; public enum NavigationViewVisualStyle { /// - /// Standard visual style of NavigationView in Win Ui. + /// Standard visual style of navigation in WinUi 3. /// Compact, From 063bc9e742517d14eeaee7500960205d60e35a61 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Wed, 24 Aug 2022 22:33:57 +0200 Subject: [PATCH 06/38] Expand NavigationView properties [skip ci] --- .../Controls/Interfaces/INavigationView.cs | 25 ++++++- .../Navigation/NavigationView.Properties.cs | 70 +++++++++++++++++-- ...lStyle.cs => NavigationViewDisplayMode.cs} | 5 +- 3 files changed, 89 insertions(+), 11 deletions(-) rename src/Wpf.Ui/Controls/Navigation/{NavigationViewVisualStyle.cs => NavigationViewDisplayMode.cs} (80%) diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs index 6e8c84759..a9d7ba16c 100644 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs @@ -21,6 +21,11 @@ public interface INavigationView /// object Header { get; set; } + /// + /// Gets or sets a value that indicates whether the header is always visible. + /// + bool AlwaysShowHeader { get; set; } + /// /// Gets the collection of menu items displayed in the NavigationView. /// @@ -41,6 +46,11 @@ public interface INavigationView /// object FooterMenuItemsSource { get; set; } + /// + /// Gets or sets the selected item. + /// + object SelectedItem { get; set; } + /// /// Gets or sets a UI element that is shown at the top of the control, below the pane if PaneDisplayMode is Top. /// @@ -73,9 +83,20 @@ public interface INavigationView double OpenPaneLength { get; set; } /// - /// Determines the visual style of the NavigationView. + /// Gets or sets the content for the pane header. + /// + object PaneHeader { get; set; } + + /// + /// Gets or sets the content for the pane footer. + /// + object PaneFooter { get; set; } + + /// + /// Gets a value that specifies how the pane and content areas of a NavigationView are being shown. + /// It is not the same DisplayMode as in WinUi. /// - NavigationViewVisualStyle VisualStyle { get; set; } + NavigationViewDisplayMode DisplayMode { get; set; } /// /// Occurs when the NavigationView pane is opened. diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs index 9ba626e86..a2a664326 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs @@ -20,6 +20,13 @@ public partial class NavigationView typeof(object), typeof(NavigationView), new FrameworkPropertyMetadata(((object)null!))); + /// + /// Property for . + /// + public static readonly DependencyProperty AlwaysShowHeaderProperty = DependencyProperty.Register(nameof(AlwaysShowHeader), + typeof(bool), typeof(NavigationView), + new FrameworkPropertyMetadata(false)); + /// /// Property for . /// @@ -48,6 +55,13 @@ public partial class NavigationView typeof(object), typeof(NavigationView), new FrameworkPropertyMetadata(((object)null!))); + /// + /// Property for . + /// + public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + /// /// Property for . /// @@ -91,11 +105,25 @@ public partial class NavigationView new FrameworkPropertyMetadata(0D)); /// - /// Property for . + /// Property for . + /// + public static readonly DependencyProperty PaneHeaderProperty = DependencyProperty.Register(nameof(PaneHeader), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + + /// + /// Property for . + /// + public static readonly DependencyProperty PaneFooterProperty = DependencyProperty.Register(nameof(PaneFooter), + typeof(object), typeof(NavigationView), + new FrameworkPropertyMetadata(((object)null!))); + + /// + /// Property for . /// - public static readonly DependencyProperty VisualStyleProperty = DependencyProperty.Register(nameof(VisualStyle), - typeof(NavigationViewVisualStyle), typeof(NavigationView), - new FrameworkPropertyMetadata(NavigationViewVisualStyle.Compact)); + public static readonly DependencyProperty DisplayModeProperty = DependencyProperty.Register(nameof(DisplayMode), + typeof(NavigationViewDisplayMode), typeof(NavigationView), + new FrameworkPropertyMetadata(NavigationViewDisplayMode.Compact)); /// public object Header @@ -104,6 +132,13 @@ public object Header set => SetValue(HeaderProperty, value); } + /// + public bool AlwaysShowHeader + { + get => (bool)GetValue(AlwaysShowHeaderProperty); + set => SetValue(AlwaysShowHeaderProperty, value); + } + /// public IList MenuItems { @@ -132,6 +167,13 @@ public object FooterMenuItemsSource set => SetValue(FooterMenuItemsSourceProperty, value); } + /// + public object SelectedItem + { + get => GetValue(SelectedItemProperty); + set => SetValue(SelectedItemProperty, value); + } + /// public object ContentOverlay { @@ -175,9 +217,23 @@ public double OpenPaneLength } /// - public NavigationViewVisualStyle VisualStyle + public object PaneHeader + { + get => GetValue(PaneHeaderProperty); + set => SetValue(PaneHeaderProperty, value); + } + + /// + public object PaneFooter + { + get => GetValue(PaneFooterProperty); + set => SetValue(PaneFooterProperty, value); + } + + /// + public NavigationViewDisplayMode DisplayMode { - get => (NavigationViewVisualStyle)GetValue(VisualStyleProperty); - set => SetValue(VisualStyleProperty, value); + get => (NavigationViewDisplayMode)GetValue(DisplayModeProperty); + set => SetValue(DisplayModeProperty, value); } } diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs similarity index 80% rename from src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs rename to src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs index 6bff2eef4..3077d0aae 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewVisualStyle.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs @@ -6,9 +6,10 @@ namespace Wpf.Ui.Controls.Navigation; /// -/// Defines constants that specify visual style of the NavigationView. +/// Defines constants that specify how the pane is shown in a NavigationView. +/// It is not the same DisplayMode as in WinUi. /// -public enum NavigationViewVisualStyle +public enum NavigationViewDisplayMode { /// /// Standard visual style of navigation in WinUi 3. From 0ae73fa2d7fc18ae1c6e1b411edb817420996f66 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:21:23 +0200 Subject: [PATCH 07/38] Update manifest file --- src/Wpf.Ui/VisualStudioToolsManifest.xml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Wpf.Ui/VisualStudioToolsManifest.xml b/src/Wpf.Ui/VisualStudioToolsManifest.xml index 2b41920b5..4acc1fbb1 100644 --- a/src/Wpf.Ui/VisualStudioToolsManifest.xml +++ b/src/Wpf.Ui/VisualStudioToolsManifest.xml @@ -23,13 +23,10 @@ - - - - - - - + + + + From d2a3cdeef072e97f7de0c7167af3476b60d76119 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:21:50 +0200 Subject: [PATCH 08/38] Implement Pane Display Mode --- .../NavigationViewPaneDisplayMode.cs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewPaneDisplayMode.cs diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewPaneDisplayMode.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewPaneDisplayMode.cs new file mode 100644 index 000000000..4612bfcc0 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewPaneDisplayMode.cs @@ -0,0 +1,37 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +namespace Wpf.Ui.Controls.Navigation; + +/// +/// Defines constants that specify how and where the NavigationView pane is shown. +/// +public enum NavigationViewPaneDisplayMode +{ + /// + /// The pane is shown on the left side of the control. Only the pane icons are shown by default. + /// Standard visual style of navigation in WinUi 3. + /// + LeftCompact, + + /// + /// Wide buttons, with full titles, similar to the settings app for Windows 11. + /// + LeftWide, + + /// + /// Modern, tiled style of navigation, similar to the Windows Store app. + /// + LeftFluent, + + /// + /// The pane is shown at the top of the control. + /// + Top +} + From e6894ccb86277a41965c29768bc45cb1fd7f0783 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:22:10 +0200 Subject: [PATCH 09/38] Add styles for separator --- .../Navigation/NavigationViewItemSeparator.cs | 4 +++ .../Controls/NavigationViewItemSeparator.xaml | 36 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Wpf.Ui/Styles/Controls/NavigationViewItemSeparator.xaml diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs index 0cf5835b7..bc1a86687 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemSeparator.cs @@ -6,6 +6,8 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. +using System.ComponentModel; + namespace Wpf.Ui.Controls.Navigation; // https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitemseparator?view=winrt-22621 @@ -13,6 +15,8 @@ namespace Wpf.Ui.Controls.Navigation; /// /// Represents a line that separates menu items in a NavigationMenu. /// +[ToolboxItem(true)] +[System.Drawing.ToolboxBitmap(typeof(NavigationViewItemSeparator), "NavigationViewItemSeparator.bmp")] public class NavigationViewItemSeparator : System.Windows.Controls.Separator { } diff --git a/src/Wpf.Ui/Styles/Controls/NavigationViewItemSeparator.xaml b/src/Wpf.Ui/Styles/Controls/NavigationViewItemSeparator.xaml new file mode 100644 index 000000000..894f5f37e --- /dev/null +++ b/src/Wpf.Ui/Styles/Controls/NavigationViewItemSeparator.xaml @@ -0,0 +1,36 @@ + + + + + + + \ No newline at end of file From 3206ff2974ec819dad9f313e0bfbbdd52f786c04 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:22:18 +0200 Subject: [PATCH 10/38] Add styles for header --- .../Navigation/NavigationViewItemHeader.cs | 87 ++++++++++++++++++- .../Controls/NavigationViewItemHeader.xaml | 71 +++++++++++++++ 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/Wpf.Ui/Styles/Controls/NavigationViewItemHeader.xaml diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs index 9d98a7266..0d41aef07 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItemHeader.cs @@ -6,6 +6,11 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. +using System.ComponentModel; +using System.Windows; +using System.Windows.Media; +using Wpf.Ui.Controls.Interfaces; + namespace Wpf.Ui.Controls.Navigation; // https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitemheader?view=winrt-22621 @@ -13,6 +18,86 @@ namespace Wpf.Ui.Controls.Navigation; /// /// Represents a header for a group of menu items in a NavigationMenu. /// -public class NavigationViewItemHeader : System.Windows.Controls.Control +[ToolboxItem(true)] +[System.Drawing.ToolboxBitmap(typeof(NavigationViewItemHeader), "NavigationViewItemHeader.bmp")] +public class NavigationViewItemHeader : System.Windows.Controls.Control, IIconControl { + /// + /// Property for . + /// + public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), + typeof(string), typeof(NavigationViewItemHeader), + new PropertyMetadata(string.Empty)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), + typeof(Common.SymbolRegular), typeof(NavigationViewItemHeader), + new PropertyMetadata(Common.SymbolRegular.Empty)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconFilledProperty = DependencyProperty.Register(nameof(IconFilled), + typeof(bool), typeof(NavigationViewItemHeader), new PropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconForegroundProperty = DependencyProperty.Register(nameof(IconForeground), + typeof(Brush), typeof(NavigationViewItemHeader), new FrameworkPropertyMetadata(SystemColors.ControlTextBrush, + FrameworkPropertyMetadataOptions.Inherits)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register(nameof(IconSize), + typeof(double), typeof(NavigationViewItemHeader), new FrameworkPropertyMetadata(13d)); + + /// + /// Text presented in the header element. + /// + [Bindable(true)] + public string Text + { + get => (string)GetValue(TextProperty); + set => SetValue(TextProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public Common.SymbolRegular Icon + { + get => (Common.SymbolRegular)GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public bool IconFilled + { + get => (bool)GetValue(IconFilledProperty); + set => SetValue(IconFilledProperty, value); + } + + /// + /// Foreground of the . + /// + [Bindable(true), Category("Appearance")] + public Brush IconForeground + { + get => (Brush)GetValue(IconForegroundProperty); + set => SetValue(IconForegroundProperty, value); + } + + /// + /// Font size of the . + /// + [Bindable(true), Category("Appearance")] + public double IconSize + { + get => (double)GetValue(IconSizeProperty); + set => SetValue(IconSizeProperty, value); + } } diff --git a/src/Wpf.Ui/Styles/Controls/NavigationViewItemHeader.xaml b/src/Wpf.Ui/Styles/Controls/NavigationViewItemHeader.xaml new file mode 100644 index 000000000..72393ee21 --- /dev/null +++ b/src/Wpf.Ui/Styles/Controls/NavigationViewItemHeader.xaml @@ -0,0 +1,71 @@ + + + + + + + \ No newline at end of file From 0839eaf00c542fae38d52b8f5df70e251603f16d Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:22:28 +0200 Subject: [PATCH 11/38] Update global xaml --- src/Wpf.Ui/Styles/Wpf.Ui.xaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Wpf.Ui/Styles/Wpf.Ui.xaml b/src/Wpf.Ui/Styles/Wpf.Ui.xaml index 0db00317c..5215649c8 100644 --- a/src/Wpf.Ui/Styles/Wpf.Ui.xaml +++ b/src/Wpf.Ui/Styles/Wpf.Ui.xaml @@ -49,6 +49,9 @@ + + + From 33aa699b8f4711a3fd88d8a3bab6b89cbdba0e73 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:22:55 +0200 Subject: [PATCH 12/38] Base logic representation --- .../Controls/Interfaces/INavigationView.cs | 36 ++- .../Interfaces/INavigationViewItem.cs | 58 +++++ .../Navigation/NavigationView.Events.cs | 40 ++++ .../Navigation/NavigationView.Navigation.cs | 205 +++++++++++++++++- .../Navigation/NavigationView.Parent.cs | 45 ++++ .../Navigation/NavigationView.Properties.cs | 154 ++++++++++--- .../NavigationView.TemplateParts.cs | 60 +++++ .../NavigationViewContentPresenter.cs | 35 +++ .../Navigation/NavigationViewDisplayMode.cs | 28 --- .../Controls/Navigation/NavigationViewItem.cs | 200 ++++++++++++++++- 10 files changed, 791 insertions(+), 70 deletions(-) create mode 100644 src/Wpf.Ui/Controls/Interfaces/INavigationViewItem.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationView.Parent.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationView.TemplateParts.cs create mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewContentPresenter.cs delete mode 100644 src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs index a9d7ba16c..82110ed88 100644 --- a/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationView.cs @@ -6,7 +6,9 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. -using System.Collections.Generic; +using System.Collections; +using System.Windows.Controls; +using Wpf.Ui.Animations; using Wpf.Ui.Controls.Navigation; namespace Wpf.Ui.Controls.Interfaces; @@ -29,7 +31,7 @@ public interface INavigationView /// /// Gets the collection of menu items displayed in the NavigationView. /// - IList MenuItems { get; set; } + IList MenuItems { get; set; } /// /// Gets or sets an object source used to generate the content of the NavigationView menu. @@ -39,7 +41,7 @@ public interface INavigationView /// /// Gets the list of objects to be used as navigation items in the footer menu. /// - IList FooterMenuItems { get; set; } + IList FooterMenuItems { get; set; } /// /// Gets or sets the object that represents the navigation items to be used in the footer menu. @@ -47,9 +49,9 @@ public interface INavigationView object FooterMenuItemsSource { get; set; } /// - /// Gets or sets the selected item. + /// Gets the selected item. /// - object SelectedItem { get; set; } + INavigationViewItem SelectedItem { get; } /// /// Gets or sets a UI element that is shown at the top of the control, below the pane if PaneDisplayMode is Top. @@ -94,9 +96,29 @@ public interface INavigationView /// /// Gets a value that specifies how the pane and content areas of a NavigationView are being shown. - /// It is not the same DisplayMode as in WinUi. + /// It is not the same PaneDisplayMode as in WinUi. /// - NavigationViewDisplayMode DisplayMode { get; set; } + NavigationViewPaneDisplayMode PaneDisplayMode { get; set; } + + /// + /// Gets or sets an AutoSuggestBox to be displayed in the NavigationView. + /// + AutoSuggestBox AutoSuggestBox { get; set; } + + /// + /// Template Property for and . + /// + ControlTemplate ItemTemplate { get; set; } + + /// + /// Gets or sets a value deciding how long the effect of the transition between the pages should take. + /// + int TransitionDuration { get; set; } + + /// + /// Gets or sets type of transitions during navigation. + /// + TransitionType TransitionType { get; set; } /// /// Occurs when the NavigationView pane is opened. diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationViewItem.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationViewItem.cs new file mode 100644 index 000000000..d02c74fbe --- /dev/null +++ b/src/Wpf.Ui/Controls/Interfaces/INavigationViewItem.cs @@ -0,0 +1,58 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System; +using System.Collections; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; + +namespace Wpf.Ui.Controls.Interfaces; + +/// +/// Represents the container for an item in a NavigationView control. +/// +public interface INavigationViewItem +{ + /// + /// Gets the collection of menu items displayed in the NavigationView. + /// + IList MenuItems { get; set; } + + /// + /// Gets or sets an object source used to generate the content of the NavigationView menu. + /// + object MenuItemsSource { get; set; } + + /// + /// Gets information whether the current element is active. + /// + bool IsActive { get; } + + /// + /// A unique tag used by the parent navigation system for the purpose of searching and navigating. + /// + public string TargetPageTag { get; set; } + + /// + /// The type of the page to be navigated. (Should be derived from ). + /// + public Type TargetPageType { get; set; } + + /// + /// Template Property + /// + public ControlTemplate Template { get; set; } + + /// + /// Add / Remove ClickEvent handler. + /// + [Category("Behavior")] + public event RoutedEventHandler Click; +} + diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs index 90feb308d..4a797fd01 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Events.cs @@ -76,4 +76,44 @@ public event NavigationViewEvent BackRequested add => AddHandler(BackRequestedEvent, value); remove => RemoveHandler(BackRequestedEvent, value); } + + /// + /// Raises the pane opened event. + /// + protected virtual void OnPaneOpened() + { + RaiseEvent(new RoutedEventArgs(PaneOpenedEvent)); + } + + /// + /// Raises the pane closed event. + /// + protected virtual void OnPaneClosed() + { + RaiseEvent(new RoutedEventArgs(PaneClosedEvent)); + } + + /// + /// Raises the selection changed event. + /// + protected virtual void OnSelectionChanged() + { + RaiseEvent(new RoutedEventArgs(SelectionChangedEvent)); + } + + /// + /// Raises the item invoked event. + /// + protected virtual void OnItemInvoked() + { + RaiseEvent(new RoutedEventArgs(ItemInvokedEvent)); + } + + /// + /// Raises the item invoked event. + /// + protected virtual void OnBackRequested() + { + RaiseEvent(new RoutedEventArgs(BackRequestedEvent)); + } } diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs index db35d70cc..3018968b0 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Navigation.cs @@ -6,6 +6,11 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. +using System; +using System.Collections; +using System.ComponentModel; +using System.Windows; +using System.Windows.Media; using Wpf.Ui.Controls.Interfaces; namespace Wpf.Ui.Controls.Navigation; @@ -15,6 +20,204 @@ namespace Wpf.Ui.Controls.Navigation; /// /// Represents a container that enables navigation of app content. It has a header, a view for the main content, and a menu pane for navigation commands. /// -public partial class NavigationView : System.Windows.Controls.Control, INavigationView +[ToolboxItem(true)] +[System.Drawing.ToolboxBitmap(typeof(NavigationView), "NavigationView.bmp")] +public partial class NavigationView : System.Windows.Controls.ContentControl, INavigationView { + /// + public INavigationViewItem SelectedItem { get; private set; } + + /// + /// Static constructor which overrides default property metadata. + /// + static NavigationView() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(NavigationView), new FrameworkPropertyMetadata(typeof(NavigationView))); + } + + public NavigationView() + { + SelectedItem = null; + NavigationParent = this; + + Unloaded += OnUnloaded; + SizeChanged += OnSizeChanged; + } + + /// + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + if (MenuItems is { Count: > 0 }) + MenuItemsSource = MenuItems; + + if (FooterMenuItems is { Count: > 0 }) + FooterMenuItemsSource = FooterMenuItems; + + if (ItemTemplate != null) + UpdateMenuItemsTemplate(); + + UpdateActiveNavigationViewItem(); + } + + /// + protected override void OnRender(DrawingContext drawingContext) + { + base.OnRender(drawingContext); + } + + /// + /// This virtual method is called when this element is detached form a loaded tree. + /// + protected virtual void OnUnloaded(object sender, RoutedEventArgs e) + { + } + + /// + /// This virtual method is called when is clicked. + /// + protected virtual void OnBackButtonClick(object sender, RoutedEventArgs e) + { + System.Diagnostics.Debug.WriteLine("Back"); + } + + /// + /// This virtual method is called when is clicked. + /// + protected virtual void OnToggleButtonClick(object sender, RoutedEventArgs e) + { + System.Diagnostics.Debug.WriteLine("Toggle"); + } + + /// + /// This virtual method is called when ActualWidth or ActualHeight (or both) changed. + /// + protected virtual void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + } + + /// + /// This virtual method is called when source of the menu items is changed. + /// + protected virtual void OnMenuItemsSourceChanged() + { + if (MenuItemsSource == null) + return; + + if (MenuItemsSource is IEnumerable enumerableItemsSource) + foreach (var singleMenuItem in enumerableItemsSource) + if (singleMenuItem is NavigationViewItem singleNavigationViewItem) + UpdateSingleMenuItem(singleNavigationViewItem); + + UpdateActiveNavigationViewItem(); + } + + /// + /// This virtual method is called when source of the footer menu items is changed. + /// + protected virtual void OnFooterMenuItemsSourceChanged() + { + if (FooterMenuItemsSource is IEnumerable enumerableItemsSource) + foreach (var singleMenuItem in enumerableItemsSource) + if (singleMenuItem is NavigationViewItem singleNavigationViewItem) + UpdateSingleMenuItem(singleNavigationViewItem); + + UpdateActiveNavigationViewItem(); + } + + /// + /// This virtual method is called when is changed. + /// + protected virtual void OnItemTemplateChanged() + { + UpdateMenuItemsTemplate(); + } + + internal void UpdateSingleMenuItem(NavigationViewItem navigationViewItem) + { + System.Diagnostics.Debug.WriteLine($"DEBUG | {navigationViewItem.GetHashCode()} - {navigationViewItem.TargetPageTag ?? "NO_TAG"} | REGISTERED"); + + navigationViewItem.Click -= OnNavigationViewItemClick; + navigationViewItem.Click += OnNavigationViewItemClick; + } + + private void OnNavigationViewItemClick(object sender, RoutedEventArgs e) + { + if (sender is not INavigationViewItem navigationViewItem) + return; + + OnItemInvoked(); + + if (navigationViewItem == SelectedItem) + return; + + SelectedItem = navigationViewItem; + + UpdateActiveNavigationViewItem(); + + System.Diagnostics.Debug.WriteLine($"DEBUG | {navigationViewItem.GetHashCode()} - {navigationViewItem.TargetPageTag ?? "NO_TAG"} | CLICKED"); + } + + private void UpdateMenuItemsTemplate() + { + if (MenuItemsSource is IEnumerable enumerableItemsSource) + foreach (var singleMenuItem in enumerableItemsSource) + if (singleMenuItem is NavigationViewItem singleNavigationViewItem) + if (ItemTemplate != null && singleNavigationViewItem.Template != ItemTemplate) + singleNavigationViewItem.Template = ItemTemplate; + + if (FooterMenuItemsSource is IEnumerable enumerableFooterItemsSource) + foreach (var singleMenuItem in enumerableFooterItemsSource) + if (singleMenuItem is NavigationViewItem singleNavigationViewItem) + if (ItemTemplate != null && singleNavigationViewItem.Template != ItemTemplate) + singleNavigationViewItem.Template = ItemTemplate; + } + + private void UpdateActiveNavigationViewItem() + { + if (MenuItemsSource is IEnumerable enumerableMenuItems) + { + foreach (var singleMenuItem in enumerableMenuItems) + { + if (singleMenuItem is not NavigationViewItem navigationViewItem) + continue; + + navigationViewItem.IsActive = navigationViewItem == SelectedItem; + + if (navigationViewItem.MenuItems is IEnumerable enumerableSubMenuItems) + { + foreach (var singleSubMenuItem in enumerableSubMenuItems) + { + if (singleSubMenuItem is not NavigationViewItem navigationViewSubItem) + continue; + + navigationViewSubItem.IsActive = navigationViewSubItem == SelectedItem; + } + } + } + } + + if (FooterMenuItemsSource is IEnumerable enumerableFooterMenuItems) + { + foreach (var singleFooterMenuItem in enumerableFooterMenuItems) + { + if (singleFooterMenuItem is not NavigationViewItem navigationViewItem) + continue; + + navigationViewItem.IsActive = navigationViewItem == SelectedItem; + + if (navigationViewItem.MenuItems is IEnumerable enumerableSubMenuItems) + { + foreach (var singleSubMenuItem in enumerableSubMenuItems) + { + if (singleSubMenuItem is not NavigationViewItem navigationViewSubItem) + continue; + + navigationViewSubItem.IsActive = navigationViewSubItem == SelectedItem; + } + } + } + } + } } diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Parent.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Parent.cs new file mode 100644 index 000000000..b31f439f3 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Parent.cs @@ -0,0 +1,45 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Windows; +using Wpf.Ui.Controls.Interfaces; + +namespace Wpf.Ui.Controls.Navigation; + +public partial class NavigationView +{ + /// + /// Attached property for 's to get its parent. + /// + internal static readonly DependencyProperty NavigationParentProperty = DependencyProperty.RegisterAttached( + nameof(NavigationParent), typeof(INavigationView), typeof(INavigationView), + new FrameworkPropertyMetadata(((INavigationView)null!), FrameworkPropertyMetadataOptions.Inherits)); + + /// + /// + /// + internal INavigationView NavigationParent + { + get => (INavigationView)GetValue(NavigationParentProperty); + private set => SetValue(NavigationParentProperty, value); + } + + /// + /// Gets the parent view for its children. + /// + /// + /// Instance of the or . + internal static NavigationView GetNavigationParent(T navigationItem) + where T : DependencyObject, INavigationViewItem + { + if (navigationItem.GetValue(NavigationParentProperty) is NavigationView navigationView) + return navigationView; + + return null; + } +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs index a2a664326..3bad93006 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.Properties.cs @@ -6,8 +6,12 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. +using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Windows; +using System.Windows.Controls; +using Wpf.Ui.Animations; namespace Wpf.Ui.Controls.Navigation; @@ -31,36 +35,29 @@ public partial class NavigationView /// Property for . /// public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(nameof(MenuItems), - typeof(IList), typeof(NavigationView), - new FrameworkPropertyMetadata(new List())); + typeof(IList), typeof(NavigationView), + new PropertyMetadata(new List { })); /// /// Property for . /// public static readonly DependencyProperty MenuItemsSourceProperty = DependencyProperty.Register(nameof(MenuItemsSource), typeof(object), typeof(NavigationView), - new FrameworkPropertyMetadata(((object)null!))); + new FrameworkPropertyMetadata(((object)null!), OnMenuItemsSourcePropertyChanged)); /// /// Property for . /// public static readonly DependencyProperty FooterMenuItemsProperty = DependencyProperty.Register(nameof(FooterMenuItemsProperty), - typeof(IList), typeof(NavigationView), - new FrameworkPropertyMetadata(new List())); + typeof(IList), typeof(NavigationView), + new PropertyMetadata(new List { })); /// /// Property for . /// public static readonly DependencyProperty FooterMenuItemsSourceProperty = DependencyProperty.Register(nameof(FooterMenuItemsSource), typeof(object), typeof(NavigationView), - new FrameworkPropertyMetadata(((object)null!))); - - /// - /// Property for . - /// - public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), - typeof(object), typeof(NavigationView), - new FrameworkPropertyMetadata(((object)null!))); + new FrameworkPropertyMetadata(((object)null!), OnFooterMenuItemsSourcePropertyChanged)); /// /// Property for . @@ -119,11 +116,42 @@ public partial class NavigationView new FrameworkPropertyMetadata(((object)null!))); /// - /// Property for . + /// Property for . + /// + public static readonly DependencyProperty PaneDisplayModeProperty = DependencyProperty.Register(nameof(PaneDisplayMode), + typeof(NavigationViewPaneDisplayMode), typeof(NavigationView), + new FrameworkPropertyMetadata(NavigationViewPaneDisplayMode.LeftCompact)); + + /// + /// Property for . + /// + public static readonly DependencyProperty AutoSuggestBoxProperty = DependencyProperty.Register(nameof(AutoSuggestBox), + typeof(AutoSuggestBox), typeof(NavigationView), + new FrameworkPropertyMetadata(((AutoSuggestBox)null!))); + + /// + /// Property for . /// - public static readonly DependencyProperty DisplayModeProperty = DependencyProperty.Register(nameof(DisplayMode), - typeof(NavigationViewDisplayMode), typeof(NavigationView), - new FrameworkPropertyMetadata(NavigationViewDisplayMode.Compact)); + public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register(nameof(ItemTemplate), + typeof(ControlTemplate), typeof(NavigationView), + new FrameworkPropertyMetadata( + (ControlTemplate)null!, // default value + FrameworkPropertyMetadataOptions.AffectsMeasure, + new PropertyChangedCallback(OnItemTemplatePropertyChanged))); + + /// + /// Property for . + /// + public static readonly DependencyProperty TransitionDurationProperty = DependencyProperty.Register(nameof(TransitionDuration), + typeof(int), typeof(NavigationView), + new FrameworkPropertyMetadata(200)); + + /// + /// Property for . + /// + public static readonly DependencyProperty TransitionTypeProperty = DependencyProperty.Register(nameof(TransitionType), + typeof(TransitionType), typeof(NavigationView), + new FrameworkPropertyMetadata(TransitionType.FadeInWithSlide)); /// public object Header @@ -140,38 +168,45 @@ public bool AlwaysShowHeader } /// - public IList MenuItems + public IList MenuItems { - get => (IList)GetValue(MenuItemsProperty); + get => (IList)GetValue(MenuItemsProperty); set => SetValue(MenuItemsProperty, value); } /// + [Bindable(true)] public object MenuItemsSource { get => GetValue(MenuItemsSourceProperty); - set => SetValue(MenuItemsSourceProperty, value); + set + { + if (value == null) + ClearValue(MenuItemsSourceProperty); + else + SetValue(MenuItemsSourceProperty, value); + } } /// - public IList FooterMenuItems + public IList FooterMenuItems { - get => (IList)GetValue(FooterMenuItemsProperty); + get => (IList)GetValue(FooterMenuItemsProperty); set => SetValue(FooterMenuItemsProperty, value); } /// + [Bindable(true)] public object FooterMenuItemsSource { get => GetValue(FooterMenuItemsSourceProperty); - set => SetValue(FooterMenuItemsSourceProperty, value); - } - - /// - public object SelectedItem - { - get => GetValue(SelectedItemProperty); - set => SetValue(SelectedItemProperty, value); + set + { + if (value == null) + ClearValue(FooterMenuItemsSourceProperty); + else + SetValue(FooterMenuItemsSourceProperty, value); + } } /// @@ -231,9 +266,62 @@ public object PaneFooter } /// - public NavigationViewDisplayMode DisplayMode + public NavigationViewPaneDisplayMode PaneDisplayMode { - get => (NavigationViewDisplayMode)GetValue(DisplayModeProperty); - set => SetValue(DisplayModeProperty, value); + get => (NavigationViewPaneDisplayMode)GetValue(PaneDisplayModeProperty); + set => SetValue(PaneDisplayModeProperty, value); + } + + /// + public AutoSuggestBox AutoSuggestBox + { + get => (AutoSuggestBox)GetValue(AutoSuggestBoxProperty); + set => SetValue(AutoSuggestBoxProperty, value); + } + + /// + public ControlTemplate ItemTemplate + { + get => (ControlTemplate)GetValue(ItemTemplateProperty); + set => SetValue(ItemTemplateProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public int TransitionDuration + { + get => (int)GetValue(TransitionDurationProperty); + set => SetValue(TransitionDurationProperty, value); + } + + /// + public TransitionType TransitionType + { + get => (TransitionType)GetValue(TransitionTypeProperty); + set => SetValue(TransitionTypeProperty, value); + } + + private static void OnMenuItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is not NavigationView navigationView) + return; + + navigationView.OnMenuItemsSourceChanged(); + } + + private static void OnFooterMenuItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is not NavigationView navigationView) + return; + + navigationView.OnFooterMenuItemsSourceChanged(); + } + + private static void OnItemTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is not NavigationView navigationView) + return; + + navigationView.OnItemTemplateChanged(); } } diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationView.TemplateParts.cs b/src/Wpf.Ui/Controls/Navigation/NavigationView.TemplateParts.cs new file mode 100644 index 000000000..f3d4ed7f3 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationView.TemplateParts.cs @@ -0,0 +1,60 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Windows; + +namespace Wpf.Ui.Controls.Navigation; + +[TemplatePart(Name = "PART_BackButton", Type = typeof(System.Windows.Controls.Button))] +[TemplatePart(Name = "PART_ToggleButton", Type = typeof(System.Windows.Controls.Button))] +public partial class NavigationView +{ + /// + /// Template element represented by the PART_BackButton name. + /// + private const string TemplateElementBackButton = "PART_BackButton"; + + /// + /// Template element represented by the PART_ToggleButton name. + /// + private const string TemplateElementToggleButton = "PART_ToggleButton"; + + /// + /// Control located at the top of the pane with left arrow icon. + /// + protected System.Windows.Controls.Button BackButton; + + /// + /// Control located at the top of the pane with hamburger icon. + /// + protected System.Windows.Controls.Button ToggleButton; + + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + if (GetTemplateChild(TemplateElementBackButton) is System.Windows.Controls.Button backButton) + BackButton = backButton; + + if (GetTemplateChild(TemplateElementToggleButton) is System.Windows.Controls.Button toggleButton) + ToggleButton = toggleButton; + + if (BackButton != null) + { + BackButton.Click -= OnBackButtonClick; + BackButton.Click += OnBackButtonClick; + } + + if (ToggleButton != null) + { + ToggleButton.Click -= OnToggleButtonClick; + ToggleButton.Click += OnToggleButtonClick; + } + } +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewContentPresenter.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewContentPresenter.cs new file mode 100644 index 000000000..5e73dd538 --- /dev/null +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewContentPresenter.cs @@ -0,0 +1,35 @@ +// Based on Windows UI Library +// Copyright(c) Microsoft Corporation.All rights reserved. + +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +using System.Windows; +using System.Windows.Controls; +using System.Windows.Navigation; + +namespace Wpf.Ui.Controls.Navigation; + +public class NavigationViewContentPresenter : Frame +{ + static NavigationViewContentPresenter() + { + //DefaultStyleKeyProperty.OverrideMetadata( + // typeof(NavigationViewContentPresenter), + // new FrameworkPropertyMetadata(typeof(NavigationViewContentPresenter))); + + NavigationUIVisibilityProperty.OverrideMetadata( + typeof(NavigationViewContentPresenter), + new FrameworkPropertyMetadata(NavigationUIVisibility.Hidden)); + + SandboxExternalContentProperty.OverrideMetadata( + typeof(NavigationViewContentPresenter), + new FrameworkPropertyMetadata(true)); + + JournalOwnershipProperty.OverrideMetadata( + typeof(NavigationViewContentPresenter), + new FrameworkPropertyMetadata(JournalOwnership.UsesParentJournal)); + } +} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs deleted file mode 100644 index 3077d0aae..000000000 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewDisplayMode.cs +++ /dev/null @@ -1,28 +0,0 @@ -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. -// Copyright (C) Leszek Pomianowski and WPF UI Contributors. -// All Rights Reserved. - -namespace Wpf.Ui.Controls.Navigation; - -/// -/// Defines constants that specify how the pane is shown in a NavigationView. -/// It is not the same DisplayMode as in WinUi. -/// -public enum NavigationViewDisplayMode -{ - /// - /// Standard visual style of navigation in WinUi 3. - /// - Compact, - - /// - /// Wide buttons, with full titles, similar to the settings app for Windows 11. - /// - Wide, - - /// - /// Modern, tiled style of navigation, similar to the Windows Store app. - /// - Fluent, -} diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs b/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs index 6e1e370df..ac2c012d6 100644 --- a/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs +++ b/src/Wpf.Ui/Controls/Navigation/NavigationViewItem.cs @@ -6,6 +6,14 @@ // Copyright (C) Leszek Pomianowski and WPF UI Contributors. // All Rights Reserved. +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows; +using System.Windows.Media; +using Wpf.Ui.Controls.Interfaces; + namespace Wpf.Ui.Controls.Navigation; // https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.navigationviewitem?view=winrt-22621 @@ -13,6 +21,196 @@ namespace Wpf.Ui.Controls.Navigation; /// /// Represents the container for an item in a NavigationView control. /// -public class NavigationViewItem : System.Windows.Controls.Control +[ToolboxItem(true)] +[System.Drawing.ToolboxBitmap(typeof(NavigationViewItem), "NavigationViewItem.bmp")] +public class NavigationViewItem : System.Windows.Controls.Primitives.ButtonBase, INavigationViewItem, IIconControl { + /// + /// Property for . + /// + public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(nameof(MenuItems), + typeof(IList), typeof(NavigationViewItem), + new PropertyMetadata(new List { })); + + /// + /// Property for . + /// + public static readonly DependencyProperty MenuItemsSourceProperty = DependencyProperty.Register(nameof(MenuItemsSource), + typeof(object), typeof(NavigationViewItem), + new PropertyMetadata(((object)null!), OnMenuItemsSourcePropertyChanged)); + + /// + /// Property for . + /// + public static readonly DependencyProperty HasMenuItemsProperty = DependencyProperty.Register(nameof(HasMenuItems), + typeof(bool), typeof(NavigationViewItem), new PropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(nameof(IsActive), + typeof(bool), typeof(NavigationViewItem), new PropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), + typeof(Common.SymbolRegular), typeof(NavigationViewItem), + new PropertyMetadata(Common.SymbolRegular.Empty)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconFilledProperty = DependencyProperty.Register(nameof(IconFilled), + typeof(bool), typeof(NavigationViewItem), new PropertyMetadata(false)); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconForegroundProperty = DependencyProperty.Register(nameof(IconForeground), + typeof(Brush), typeof(NavigationViewItem), new FrameworkPropertyMetadata(SystemColors.ControlTextBrush, + FrameworkPropertyMetadataOptions.Inherits)); + + /// + /// Property for . + /// + public static readonly DependencyProperty TargetPageTagProperty = DependencyProperty.Register(nameof(TargetPageTag), + typeof(string), typeof(NavigationViewItem), new PropertyMetadata(String.Empty)); + + /// + /// Property for . + /// + public static readonly DependencyProperty TargetPageTypeProperty = DependencyProperty.Register(nameof(TargetPageType), + typeof(Type), typeof(NavigationViewItem), new PropertyMetadata((Type)null!)); + + /// + public IList MenuItems + { + get => (IList)GetValue(MenuItemsProperty); + set => SetValue(MenuItemsProperty, value); + } + + /// + [Bindable(true)] + public object MenuItemsSource + { + get => GetValue(MenuItemsSourceProperty); + set + { + if (value == null) + ClearValue(MenuItemsSourceProperty); + else + SetValue(MenuItemsSourceProperty, value); + } + } + + /// + /// Gets a value indicating whether the has . + /// + [Browsable(false), ReadOnly(true)] + public bool HasMenuItems + { + get => (bool)GetValue(HasMenuItemsProperty); + private set => SetValue(HasMenuItemsProperty, value); + } + + /// + [Browsable(false), ReadOnly(true)] + public bool IsActive + { + get => (bool)GetValue(IsActiveProperty); + internal set => SetValue(IsActiveProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public Common.SymbolRegular Icon + { + get => (Common.SymbolRegular)GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public bool IconFilled + { + get => (bool)GetValue(IconFilledProperty); + set => SetValue(IconFilledProperty, value); + } + + /// + [Bindable(true), Category("Appearance")] + public Brush IconForeground + { + get => (Brush)GetValue(IconForegroundProperty); + set => SetValue(IconForegroundProperty, value); + } + + /// + public string TargetPageTag + { + get => (string)GetValue(TargetPageTagProperty); + set => SetValue(TargetPageTagProperty, value); + } + + /// + public Type TargetPageType + { + get => (Type)GetValue(TargetPageTypeProperty); + set => SetValue(TargetPageTypeProperty, value); + } + + static NavigationViewItem() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(NavigationViewItem), new FrameworkPropertyMetadata(typeof(NavigationViewItem))); + } + + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + //if (MenuItems is { Count: > 0 }) + // MenuItemsSource = MenuItems; + + if (String.IsNullOrWhiteSpace(TargetPageTag)) + TargetPageTag = Content?.ToString()!.ToLower()!.Trim() ?? String.Empty; + + //UpdateMenuItemsBindings(); + } + + private static void OnMenuItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is not NavigationViewItem navigationViewItem) + return; + + navigationViewItem.OnMenuItemsSourceChanged(); + } + + /// + /// This virtual method is called when source of the menu items is changed. + /// + protected virtual void OnMenuItemsSourceChanged() + { + UpdateMenuItemsBindings(); + } + + private void UpdateMenuItemsBindings() + { + var isNavigationViewItemHasSubItems = MenuItemsSource is ICollection { Count: > 0 }; + + HasMenuItems = isNavigationViewItemHasSubItems; + + if (!isNavigationViewItemHasSubItems) + return; + + if (NavigationView.GetNavigationParent(this) is not { } navigationView) + return; + + var current = this; + + if (MenuItemsSource is IEnumerable enumerableItemsSource) + foreach (var singleMenuItem in enumerableItemsSource) + if (singleMenuItem is NavigationViewItem singleNavigationViewItem) + navigationView.UpdateSingleMenuItem(singleNavigationViewItem); + } } From f6a8bca9efc0c0e507bea418cf116161372d3f68 Mon Sep 17 00:00:00 2001 From: pomianowski Date: Fri, 26 Aug 2022 19:23:08 +0200 Subject: [PATCH 13/38] Base starting template for the NavigationView --- .../Styles/Controls/NavigationView.xaml | 614 ++++++++++++++++++ 1 file changed, 614 insertions(+) create mode 100644 src/Wpf.Ui/Styles/Controls/NavigationView.xaml diff --git a/src/Wpf.Ui/Styles/Controls/NavigationView.xaml b/src/Wpf.Ui/Styles/Controls/NavigationView.xaml new file mode 100644 index 000000000..4490a6c37 --- /dev/null +++ b/src/Wpf.Ui/Styles/Controls/NavigationView.xaml @@ -0,0 +1,614 @@ + + + + + 40 + 40 + 1,1,1,1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +