From d3e8cd537f9089889e2ee6dfe866c2ee974dcfe6 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 1 Aug 2022 15:05:02 +0600
Subject: [PATCH 01/28] cleaned NavigationBase
---
src/Packages.props | 1 +
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 10 +-
.../Views/Pages/ExperimentalDashboard.xaml.cs | 2 +-
.../Views/Windows/ExperimentalWindow.xaml.cs | 11 +-
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 117 +-----
.../Navigation/NavigationBackButton.cs | 2 +-
.../Controls/Navigation/NavigationBase.cs | 397 +++---------------
src/Wpf.Ui/Controls/NavigationItem.cs | 2 +-
.../Mvvm/Contracts/INavigationService.cs | 27 +-
.../Mvvm/Contracts/INavigationWindow.cs | 21 +-
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 57 ++-
src/Wpf.Ui/Services/Internal/FrameManager.cs | 74 ++++
.../Services/Internal/NavigationManager.cs | 24 ++
src/Wpf.Ui/Wpf.Ui.csproj | 4 +
14 files changed, 236 insertions(+), 513 deletions(-)
create mode 100644 src/Wpf.Ui/Services/Internal/FrameManager.cs
create mode 100644 src/Wpf.Ui/Services/Internal/NavigationManager.cs
diff --git a/src/Packages.props b/src/Packages.props
index f2ca092b9..d3ada50a2 100644
--- a/src/Packages.props
+++ b/src/Packages.props
@@ -7,5 +7,6 @@
+
\ No newline at end of file
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index e9e158b98..4b9c6f646 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -96,8 +96,11 @@ public Frame GetFrame()
public INavigation GetNavigation()
=> RootNavigation;
- public bool Navigate(Type pageType)
- => RootNavigation.Navigate(pageType);
+ public void NavigateTo(Type type, object dataContext = null)
+ => RootNavigation.NavigateTo(type, dataContext);
+
+ public void NavigateTo(string pageTag, object dataContext = null)
+ => RootNavigation.NavigateTo(pageTag, dataContext);
public void SetPageService(IPageService pageService)
=> RootNavigation.PageService = pageService;
@@ -108,6 +111,7 @@ public void ShowWindow()
public void CloseWindow()
=> Close();
+
#endregion INavigationWindow methods
private void InvokeSplashScreen()
@@ -133,7 +137,7 @@ await Dispatcher.InvokeAsync(() =>
RootWelcomeGrid.Visibility = Visibility.Hidden;
RootMainGrid.Visibility = Visibility.Visible;
- Navigate(typeof(Pages.Dashboard));
+ NavigateTo(typeof(Pages.Dashboard));
_taskBarService.SetState(this, TaskBarProgressState.None);
});
diff --git a/src/Wpf.Ui.Demo/Views/Pages/ExperimentalDashboard.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/ExperimentalDashboard.xaml.cs
index e1fd83569..a8ece4934 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/ExperimentalDashboard.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Pages/ExperimentalDashboard.xaml.cs
@@ -58,7 +58,7 @@ private void ButtonExternal_OnClick(object sender, RoutedEventArgs e)
if (DataContext is not ExperimentalViewModel viewData)
return;
- viewData.ParentWindow.Navigate(typeof(ExperimentalDashboard));
+ viewData.ParentWindow.NavigateTo(typeof(ExperimentalDashboard));
}
private void TaskbarStateComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
diff --git a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
index 9e6b6d692..5f5f58364 100644
--- a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
@@ -101,7 +101,7 @@ public ExperimentalWindow(ExperimentalViewModel viewModel, IThemeService themeSe
private void RootNavigationOnLoaded(object sender, RoutedEventArgs e)
{
- RootNavigation.Navigate(0, DataContext);
+ //RootNavigation.NavigateTo(0, DataContext);
}
private void NavigationButtonTheme_OnClick(object sender, RoutedEventArgs e)
@@ -130,9 +130,6 @@ public Frame GetFrame()
public INavigation GetNavigation()
=> RootNavigation;
- public bool Navigate(Type pageType)
- => RootNavigation.Navigate(pageType);
-
public void SetPageService(IPageService pageService)
=> RootNavigation.PageService = pageService;
@@ -141,4 +138,10 @@ public void ShowWindow()
public void CloseWindow()
=> Close();
+
+ public void NavigateTo(Type type, object dataContext = null)
+ => RootNavigation.NavigateTo(type, dataContext);
+
+ public void NavigateTo(string pageTag, object dataContext = null)
+ => RootNavigation.NavigateTo(pageTag, dataContext);
}
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 3e2592e12..a8de97f0c 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -3,6 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+#nullable enable
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
@@ -29,11 +30,6 @@ public interface INavigation
///
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.
///
@@ -102,117 +98,22 @@ public interface INavigation
[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.
+ /// TODO
///
- /// Tag of the page from or .
- /// Context of the data for data binding.
- /// if the operation was successful.
- bool SetContext(string pageTag, object dataContext);
+ ///
+ ///
+ void NavigateTo(string pageTag, object? dataContext = null);
///
- /// Tires to set the DataContext for the currently displayed page.
+ /// TODO
///
- /// Data context to be set.
- void SetCurrentContext(object dataContext);
+ ///
+ ///
+ void NavigateTo(Type type, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs
index d1ffefb16..40f0b4d88 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBackButton.cs
@@ -34,6 +34,6 @@ public INavigation? Navigation
public NavigationBackButton()
{
- SetValue(CommandProperty, new Common.RelayCommand(_ => Navigation?.NavigateBack(), () => Navigation is not null && Navigation.CanGoBack));
+ SetValue(CommandProperty, new Common.RelayCommand(_ => Navigation?.NavigateTo(".."), () => Navigation is not null && Navigation.CanGoBack));
}
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index bc8ea838c..c9b69d3eb 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -4,19 +4,19 @@
// All Rights Reserved.
#nullable enable
-#pragma warning disable CS8600
-#pragma warning disable CS8603
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Collections.Specialized;
+using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
+using Microsoft.Toolkit.Diagnostics;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
-using Wpf.Ui.Mvvm.Interfaces;
+using Wpf.Ui.Services.Internal;
namespace Wpf.Ui.Controls.Navigation;
@@ -25,24 +25,24 @@ namespace Wpf.Ui.Controls.Navigation;
///
public abstract class NavigationBase : System.Windows.Controls.Control, INavigation
{
- ///
- /// Service used for navigation purposes.
- ///
- private readonly Services.Internal.NavigationService? _navigationService;
+ private FrameManager _frameManager = null!;
+ private readonly NavigationManager _navigationManager;
+
+ #region DependencyProperties
///
/// Property for .
///
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(nameof(Items),
typeof(ObservableCollection), typeof(NavigationBase),
- new PropertyMetadata((ObservableCollection)null, OnItemsChanged));
+ new PropertyMetadata(new ObservableCollection()));
///
/// Property for .
///
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(nameof(Footer),
typeof(ObservableCollection), typeof(NavigationBase),
- new PropertyMetadata((ObservableCollection)null, OnFooterChanged));
+ new PropertyMetadata(new ObservableCollection()));
///
/// Property for .
@@ -57,7 +57,7 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
///
public static readonly DependencyProperty FrameProperty = DependencyProperty.Register(nameof(Frame),
typeof(Frame), typeof(NavigationBase),
- new PropertyMetadata((Frame)null, OnFrameChanged));
+ new PropertyMetadata());
///
/// Property for .
@@ -98,17 +98,21 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
nameof(NavigationParent), typeof(INavigation), typeof(NavigationBase),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));
+ #endregion
+
+ #region Properties
+
///
public ObservableCollection Items
{
- get => GetValue(ItemsProperty) as ObservableCollection;
+ get => (GetValue(ItemsProperty) as ObservableCollection)!;
set => SetValue(ItemsProperty, value);
}
///
public ObservableCollection Footer
{
- get => GetValue(FooterProperty) as ObservableCollection;
+ get => (GetValue(FooterProperty) as ObservableCollection)!;
set => SetValue(FooterProperty, value);
}
@@ -135,9 +139,9 @@ public Animations.TransitionType TransitionType
}
///
- public Frame? Frame
+ public Frame Frame
{
- get => GetValue(FrameProperty) as Frame;
+ get => (GetValue(FrameProperty) as Frame)!;
set => SetValue(FrameProperty, value);
}
@@ -161,6 +165,8 @@ internal INavigation NavigationParent
private set => SetValue(NavigationParentProperty, value);
}
+ #endregion
+
#region Events
///
@@ -207,17 +213,10 @@ public event RoutedNavigationEvent NavigatedBackward
#endregion
///
- public IPageService? PageService
- {
- get => _navigationService?.GetService();
- set => _navigationService?.SetService(value);
- }
+ public IPageService? PageService { get; set; }
///
- public int PreviousPageIndex => _navigationService?.GetPreviousId() ?? 0;
-
- ///
- public bool CanGoBack => _navigationService is not null && _navigationService.CanGoBack;
+ public bool CanGoBack { get; private set; }
///
public INavigationItem? Current { get; internal set; }
@@ -241,18 +240,7 @@ static NavigationBase()
///
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);
+ _navigationManager = new NavigationManager();
// Let the NavigationItem children be able to get me.
NavigationParent = this;
@@ -261,204 +249,40 @@ protected NavigationBase()
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)
+ public void ClearCache()
{
- if (_navigationService == null)
- return false;
-
- return _navigationService.SetContext(pageId, dataContext);
+
}
///
- public void Flush()
+ public void NavigateTo(string pageTag, object? dataContext = null)
{
- Items.Clear();
- Footer.Clear();
-
- Current = (INavigationItem)null;
+
}
///
- public void ClearCache()
+ public void NavigateTo(Type type, object? dataContext = null)
{
- if (_navigationService == null)
- return;
-
- _navigationService.ClearCache();
+
}
///
- /// Updates property and modifies Active attribute of navigation items.
+ /// This virtual method is called when is loaded.
///
- private void UpdateItems()
+ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
{
- var currentTag = _navigationService?.GetCurrentTag() ?? String.Empty;
+ if (DesignerProperties.GetIsInDesignMode(this))
+ return;
- 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;
- }
- }
+ Guard.IsNotNull(Frame, nameof(Frame));
- 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;
- }
- }
- }
+ _frameManager = new FrameManager(Frame, TransitionDuration, TransitionType);
- ///
- /// This virtual method is called when is loaded.
- ///
- protected virtual void OnLoaded(object sender, RoutedEventArgs e)
- {
- UpdateServiceItems();
+ if (SelectedPageIndex > -1)
+ _navigationManager.NavigateToById(SelectedPageIndex);
- if (PageService == null && Frame != null && SelectedPageIndex > -1)
- Navigate(SelectedPageIndex);
+ InitializeServiceItems();
// If we are using the MVVM model, do not use the cache.
if (Precache)
@@ -554,91 +378,7 @@ protected virtual void OnNavigationItemClicked(object sender, RoutedEventArgs e)
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);
+ NavigateTo(navigationItem.PageTag);
}
private static void OnTransitionDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -646,10 +386,7 @@ private static void OnTransitionDurationChanged(DependencyObject d, DependencyPr
if (d is not NavigationBase navigation)
return;
- if (navigation._navigationService == null)
- return;
-
- navigation._navigationService.TransitionDuration = (int)e.NewValue;
+ //navigation._navigationService.TransitionDuration = (int)e.NewValue;
}
private static void OnTransitionTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -657,10 +394,7 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
if (d is not NavigationBase navigation)
return;
- if (navigation._navigationService == null)
- return;
-
- navigation._navigationService.TransitionType = (Animations.TransitionType)e.NewValue;
+ //navigation._navigationService.TransitionType = (Animations.TransitionType)e.NewValue;
}
///
@@ -676,47 +410,18 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
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);
+ SubscribeToClickEventForEnumerable(Items);
+ SubscribeToClickEventForEnumerable(Footer);
}
- private void NavigateInternal(int arg, bool updateItems)
+ private void SubscribeToClickEventForEnumerable(IEnumerable enumerable)
{
- SelectedPageIndex = _navigationService?.GetCurrentId() ?? +arg;
-
- if (updateItems)
- UpdateItems();
-
- OnNavigated();
+ foreach (var addedItem in enumerable)
+ {
+ if (addedItem is not INavigationItem item) continue;
- if (SelectedPageIndex > (_navigationService?.GetPreviousId() ?? +arg))
- OnNavigatedForward();
- else
- OnNavigatedBackward();
+ item.Click -= OnNavigationItemClicked; // Unsafe - Remove duplicates
+ item.Click += OnNavigationItemClicked;
+ }
}
}
diff --git a/src/Wpf.Ui/Controls/NavigationItem.cs b/src/Wpf.Ui/Controls/NavigationItem.cs
index 36fc11fb3..496a57364 100644
--- a/src/Wpf.Ui/Controls/NavigationItem.cs
+++ b/src/Wpf.Ui/Controls/NavigationItem.cs
@@ -293,7 +293,7 @@ protected override void OnKeyDown(KeyEventArgs e)
{
e.Handled = true;
- navigation.Navigate(pageTag);
+ navigation.NavigateTo(pageTag);
}
break;
}
diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
index 1914de8c0..bbf3feca5 100644
--- a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
@@ -15,6 +15,14 @@ namespace Wpf.Ui.Mvvm.Contracts;
///
public interface INavigationService
{
+
+ ///
+ /// TODO
+ ///
+ ///
+ ///
+ void Initialize(INavigation navigation, IPageService pageService);
+
///
/// Provides direct access to the used in navigation.
///
@@ -38,7 +46,6 @@ public interface INavigationService
///
/// Instance of the .
void SetNavigationControl(INavigation navigation);
-
///
/// Lets you attach the service that delivers page instances to .
///
@@ -46,20 +53,14 @@ public interface INavigationService
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 .
+ /// Lets you navigate to the selected page based on it's tag. Should be used with .
///
- /// Id of the page.
- bool Navigate(int pageId);
+ /// Tag of the page.
+ void Navigate(string pageTag);
///
- /// Lets you navigate to the selected page based on it's tag. Should be used with .
+ /// TODO
///
- /// Tag of the page.
- bool Navigate(string pageTag);
+ ///
+ void Navigate(Type type);
}
diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs
index 6d46035a2..62515ebe4 100644
--- a/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs
+++ b/src/Wpf.Ui/Mvvm/Contracts/INavigationWindow.cs
@@ -3,6 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+#nullable enable
using System;
using System.Windows.Controls;
using Wpf.Ui.Controls.Interfaces;
@@ -27,12 +28,6 @@ public interface INavigationWindow
/// 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 .
///
@@ -48,4 +43,18 @@ public interface INavigationWindow
/// Triggers the command to close a window.
///
void CloseWindow();
+
+ ///
+ /// TODO
+ ///
+ ///
+ ///
+ void NavigateTo(string pageTag, object? dataContext = null);
+
+ ///
+ /// TODO
+ ///
+ ///
+ ///
+ void NavigateTo(Type type, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 4818c102d..92ea1ee0f 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -3,8 +3,10 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+#nullable enable
using System;
using System.Windows.Controls;
+using Microsoft.Toolkit.Diagnostics;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
@@ -15,28 +17,41 @@ namespace Wpf.Ui.Mvvm.Services;
///
public partial class NavigationService : INavigationService
{
+ private INavigation? _navigationControl;
+
///
/// Locally attached page service.
///
- private IPageService _pageService;
+ private IPageService? _pageService;
///
/// Control representing navigation.
///
- protected INavigation NavigationControl;
+ private INavigation NavigationControl
+ {
+ get
+ {
+ Guard.IsNotNull(_navigationControl, nameof(NavigationControl));
+ return _navigationControl;
+ }
+ set => _navigationControl = value;
+ }
+
+ public void Initialize(INavigation navigation, IPageService pageService)
+ {
+ NavigationControl = navigation;
+ NavigationControl.PageService = pageService;
+ }
///
public Frame GetFrame()
{
- return NavigationControl?.Frame;
+ return NavigationControl.Frame;
}
///
public void SetFrame(Frame frame)
{
- if (NavigationControl == null)
- return;
-
NavigationControl.Frame = frame;
}
@@ -46,22 +61,19 @@ public INavigation GetNavigationControl()
return NavigationControl;
}
- ///
public void SetNavigationControl(INavigation navigation)
{
NavigationControl = navigation;
- if (_pageService != null)
+ if (_pageService is not null)
NavigationControl.PageService = _pageService;
}
- ///
public void SetPageService(IPageService pageService)
{
- if (NavigationControl == null)
+ if (_navigationControl is null)
{
_pageService = pageService;
-
return;
}
@@ -69,29 +81,14 @@ public void SetPageService(IPageService pageService)
}
///
- public bool Navigate(Type pageType)
- {
- if (NavigationControl == null)
- return false;
-
- return NavigationControl.Navigate(pageType);
- }
-
- ///
- public bool Navigate(int pageId)
+ public void Navigate(string pageTag)
{
- if (NavigationControl == null)
- return false;
-
- return NavigationControl.Navigate(pageId);
+ NavigationControl.NavigateTo(pageTag);
}
///
- public bool Navigate(string pageTag)
+ public void Navigate(Type type)
{
- if (NavigationControl == null)
- return false;
-
- return NavigationControl.Navigate(pageTag);
+ NavigationControl.NavigateTo(type);
}
}
diff --git a/src/Wpf.Ui/Services/Internal/FrameManager.cs b/src/Wpf.Ui/Services/Internal/FrameManager.cs
new file mode 100644
index 000000000..596dd60ca
--- /dev/null
+++ b/src/Wpf.Ui/Services/Internal/FrameManager.cs
@@ -0,0 +1,74 @@
+#nullable enable
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Navigation;
+using Wpf.Ui.Animations;
+using Wpf.Ui.Common.Interfaces;
+
+namespace Wpf.Ui.Services.Internal;
+
+internal sealed class FrameManager
+{
+ private readonly Frame _frame;
+ private readonly int _transitionDuration;
+ private readonly TransitionType _transitionType;
+
+ public FrameManager(Frame frame, int transitionDuration, TransitionType transitionType)
+ {
+ _frame = frame;
+ _transitionDuration = transitionDuration;
+ _transitionType = transitionType;
+
+ _frame.NavigationUIVisibility = NavigationUIVisibility.Hidden;
+
+ _frame.Navigating += OnFrameNavigating;
+ _frame.Navigated += OnFrameNavigated;
+ }
+
+
+ private void OnFrameNavigating(object sender, NavigatingCancelEventArgs e)
+ {
+ NotifyFrameContentAboutLeave();
+ }
+
+ private void OnFrameNavigated(object sender, NavigationEventArgs e)
+ {
+ _frame.NavigationService.RemoveBackEntry();
+
+ if (_transitionDuration > 0 && e.Content != null)
+ Transitions.ApplyTransition(e.Content, _transitionType, _transitionDuration);
+
+ //TODO
+ /*// 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();
+ }
+
+ private void NotifyFrameContentAboutEnter()
+ {
+ var navigationAware = GetINavigationAwareOrDefault();
+ navigationAware?.OnNavigatedTo();
+ }
+
+ private void NotifyFrameContentAboutLeave()
+ {
+ var navigationAware = GetINavigationAwareOrDefault();
+ navigationAware?.OnNavigatedFrom();
+ }
+
+ private INavigationAware? GetINavigationAwareOrDefault()
+ {
+ INavigationAware? navigationAware = _frame.Content switch
+ {
+ INavigationAware aware => aware,
+ INavigableView {ViewModel: INavigationAware viewModelNavigationAware} => viewModelNavigationAware,
+ FrameworkElement {DataContext: INavigationAware dataContextNavigationAware} => dataContextNavigationAware,
+ _ => null
+ };
+
+ return navigationAware;
+ }
+}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
new file mode 100644
index 000000000..13cfc5e09
--- /dev/null
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -0,0 +1,24 @@
+#nullable enable
+using System;
+
+namespace Wpf.Ui.Services.Internal;
+
+internal sealed class NavigationManager
+{
+ public string CurrentTag { get; private set; }
+
+ public void NavigateToByTag(string tag, object? dataContext = null)
+ {
+
+ }
+
+ public void NavigateToByType(Type type, object? dataContext = null)
+ {
+
+ }
+
+ public void NavigateToById(int id, object? dataContext = null)
+ {
+
+ }
+}
diff --git a/src/Wpf.Ui/Wpf.Ui.csproj b/src/Wpf.Ui/Wpf.Ui.csproj
index c723d1d40..01cbf0cce 100644
--- a/src/Wpf.Ui/Wpf.Ui.csproj
+++ b/src/Wpf.Ui/Wpf.Ui.csproj
@@ -71,6 +71,10 @@
+
+
+
+
From 068856e9d369e9bcb0dc049f4c36d441f9112e99 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 1 Aug 2022 18:04:23 +0600
Subject: [PATCH 02/28] initially implemented navigation
---
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 2 +-
.../Views/Windows/ExperimentalWindow.xaml.cs | 2 +-
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 11 +-
.../Controls/Navigation/NavigationBase.cs | 71 +++++----
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 6 +-
src/Wpf.Ui/Services/Internal/FrameManager.cs | 8 +-
.../Services/Internal/NavigationManager.cs | 143 +++++++++++++++++-
7 files changed, 200 insertions(+), 43 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 4b9c6f646..1ef25e160 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -103,7 +103,7 @@ public void NavigateTo(string pageTag, object dataContext = null)
=> RootNavigation.NavigateTo(pageTag, dataContext);
public void SetPageService(IPageService pageService)
- => RootNavigation.PageService = pageService;
+ => RootNavigation.SetIPageService(pageService);
public void ShowWindow()
=> Show();
diff --git a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
index 5f5f58364..a90b5fb71 100644
--- a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
@@ -131,7 +131,7 @@ public INavigation GetNavigation()
=> RootNavigation;
public void SetPageService(IPageService pageService)
- => RootNavigation.PageService = pageService;
+ => RootNavigation.SetIPageService(pageService);
public void ShowWindow()
=> Show();
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index a8de97f0c..24598007c 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -19,11 +19,6 @@ namespace Wpf.Ui.Controls.Interfaces;
///
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.
@@ -98,6 +93,12 @@ public interface INavigation
[Bindable(true), Category("Appearance")]
TransitionType TransitionType { get; set; }
+
+ ///
+ /// TODO
+ ///
+ void SetIPageService(IPageService pageService);
+
///
/// Clears all initialized instances of the pages.
///
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index c9b69d3eb..2ebbaa772 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -26,7 +26,9 @@ namespace Wpf.Ui.Controls.Navigation;
public abstract class NavigationBase : System.Windows.Controls.Control, INavigation
{
private FrameManager _frameManager = null!;
- private readonly NavigationManager _navigationManager;
+ private NavigationManager _navigationManager = null!;
+ private IPageService? _pageService;
+ private INavigationItem[] _items = null!;
#region DependencyProperties
@@ -213,13 +215,10 @@ public event RoutedNavigationEvent NavigatedBackward
#endregion
///
- public IPageService? PageService { get; set; }
+ public bool CanGoBack => _navigationManager.CanGoBack;
///
- public bool CanGoBack { get; private set; }
-
- ///
- public INavigationItem? Current { get; internal set; }
+ public INavigationItem Current => _navigationManager.Current;
///
/// Static constructor overriding default properties.
@@ -240,13 +239,17 @@ static NavigationBase()
///
protected NavigationBase()
{
- _navigationManager = new NavigationManager();
-
// Let the NavigationItem children be able to get me.
NavigationParent = this;
// Loaded does not have override
Loaded += OnLoaded;
+ Unloaded += OnUnloaded;
+ }
+
+ public void SetIPageService(IPageService pageService)
+ {
+ _pageService = pageService;
}
///
@@ -258,13 +261,15 @@ public void ClearCache()
///
public void NavigateTo(string pageTag, object? dataContext = null)
{
-
+ _navigationManager.NavigateTo(pageTag, dataContext);
+ OnNavigated();
}
///
public void NavigateTo(Type type, object? dataContext = null)
{
-
+ _navigationManager.NavigateTo(type, dataContext);
+ OnNavigated();
}
///
@@ -277,21 +282,26 @@ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
Guard.IsNotNull(Frame, nameof(Frame));
+ _items = MergeItems(Items, Footer);
+
_frameManager = new FrameManager(Frame, TransitionDuration, TransitionType);
+ _navigationManager = new NavigationManager(Frame, _pageService, _items);
if (SelectedPageIndex > -1)
- _navigationManager.NavigateToById(SelectedPageIndex);
+ {
+ _navigationManager.NavigateTo(SelectedPageIndex);
+ OnNavigated();
+ }
+ }
- InitializeServiceItems();
+ protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
+ {
+ _frameManager.Dispose();
+ _navigationManager.Dispose();
- // If we are using the MVVM model, do not use the cache.
- if (Precache)
+ foreach (var item in _items)
{
- if (PageService != null)
- throw new InvalidOperationException("The cache cannot be used if you are using IPageService.");
-
- // TODO: Precache
- //await PrecacheInstances();
+ item.Click -= OnNavigationItemClicked;
}
}
@@ -408,20 +418,27 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
return (NavigationBase?)navigationItem.GetValue(NavigationParentProperty);
}
- private void InitializeServiceItems()
+ private INavigationItem[] MergeItems(IReadOnlyList items, IReadOnlyList footer)
{
- SubscribeToClickEventForEnumerable(Items);
- SubscribeToClickEventForEnumerable(Footer);
- }
+ var overallCount = items.Count + footer.Count;
+ List overallItems = new List();
- private void SubscribeToClickEventForEnumerable(IEnumerable enumerable)
- {
- foreach (var addedItem in enumerable)
+ foreach (var addedItem in items)
{
if (addedItem is not INavigationItem item) continue;
- item.Click -= OnNavigationItemClicked; // Unsafe - Remove duplicates
item.Click += OnNavigationItemClicked;
+ overallItems.Add(item);
}
+
+ foreach (var addedItem in footer)
+ {
+ if (addedItem is not INavigationItem item) continue;
+
+ item.Click += OnNavigationItemClicked;
+ overallItems.Add(item);
+ }
+
+ return overallItems.ToArray();
}
}
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 92ea1ee0f..83fef0202 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -40,7 +40,7 @@ private INavigation NavigationControl
public void Initialize(INavigation navigation, IPageService pageService)
{
NavigationControl = navigation;
- NavigationControl.PageService = pageService;
+ NavigationControl.SetIPageService(pageService);
}
///
@@ -66,7 +66,7 @@ public void SetNavigationControl(INavigation navigation)
NavigationControl = navigation;
if (_pageService is not null)
- NavigationControl.PageService = _pageService;
+ NavigationControl.SetIPageService(_pageService);
}
public void SetPageService(IPageService pageService)
@@ -77,7 +77,7 @@ public void SetPageService(IPageService pageService)
return;
}
- NavigationControl.PageService = pageService;
+ NavigationControl.SetIPageService(pageService);
}
///
diff --git a/src/Wpf.Ui/Services/Internal/FrameManager.cs b/src/Wpf.Ui/Services/Internal/FrameManager.cs
index 596dd60ca..179d9def7 100644
--- a/src/Wpf.Ui/Services/Internal/FrameManager.cs
+++ b/src/Wpf.Ui/Services/Internal/FrameManager.cs
@@ -1,4 +1,5 @@
#nullable enable
+using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
@@ -7,7 +8,7 @@
namespace Wpf.Ui.Services.Internal;
-internal sealed class FrameManager
+internal sealed class FrameManager : IDisposable
{
private readonly Frame _frame;
private readonly int _transitionDuration;
@@ -25,6 +26,11 @@ public FrameManager(Frame frame, int transitionDuration, TransitionType transiti
_frame.Navigated += OnFrameNavigated;
}
+ public void Dispose()
+ {
+ _frame.Navigating -= OnFrameNavigating;
+ _frame.Navigated -= OnFrameNavigated;
+ }
private void OnFrameNavigating(object sender, NavigatingCancelEventArgs e)
{
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 13cfc5e09..1edd9ae4e 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -1,24 +1,157 @@
#nullable enable
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using Microsoft.Toolkit.Diagnostics;
+using Wpf.Ui.Controls.Interfaces;
+using Wpf.Ui.Mvvm.Contracts;
namespace Wpf.Ui.Services.Internal;
-internal sealed class NavigationManager
+internal sealed class NavigationManager : IDisposable
{
- public string CurrentTag { get; private set; }
+ private readonly Frame _frame;
+ private readonly INavigationItem[] _navigationItems;
+ private readonly FrameworkElement[] _instances;
+ private readonly List _history = new();
+ private readonly List _navigationStack = new();
+ private readonly IPageService? _pageService;
- public void NavigateToByTag(string tag, object? dataContext = null)
+ private bool _isBackwardsNavigated;
+ private int _previousItemId = -1;
+
+ public bool CanGoBack => _history.Count > 1;
+ public INavigationItem Current { get; private set; } = null!;
+
+ public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
+ {
+ _instances = new FrameworkElement[navigationItems.Length];
+
+ _navigationItems = navigationItems;
+ _frame = frame;
+ _pageService = pageService;
+ }
+
+ public void Dispose()
+ {
+
+ }
+
+ public void NavigateTo(string tag, object? dataContext = null)
+ {
+ Guard.IsNotNullOrEmpty(tag, nameof(tag));
+
+ if (tag == "..")
+ {
+ NavigateBack();
+ return;
+ }
+
+ var itemId = GetItemId(item => item.PageTag == tag);
+ NavigateInternal(itemId, dataContext);
+ }
+
+ public void NavigateTo(Type type, object? dataContext = null)
+ {
+ var itemId = GetItemId(serviceItem => serviceItem.PageType == type);
+ NavigateInternal(itemId, dataContext);
+ }
+
+ public void NavigateTo(int id, object? dataContext = null)
{
+ NavigateInternal(id, dataContext);
+ }
+
+ private void NavigateBack()
+ {
+ if (_history.Count <= 1)
+ return;
+ var itemId = _history[_history.Count - 2];
+ _isBackwardsNavigated = true;
+ NavigateInternal(itemId, null);
}
- public void NavigateToByType(Type type, object? dataContext = null)
+ private void NavigateInternal(int itemId, object? dataContext)
{
+ if (ReferenceEquals(Current, _navigationItems.ElementAtOrDefault(itemId)))
+ return;
+ if (_isBackwardsNavigated)
+ {
+ _isBackwardsNavigated = false;
+ _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 2]));
+ _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 1]));
+ }
+
+ _history.Add(itemId);
+
+ PerformNavigation(itemId, dataContext);
}
- public void NavigateToById(int id, object? dataContext = null)
+ #region PerformNavigation
+
+ private void PerformNavigation(int itemId, object? dataContext)
{
+ if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
+ return;
+
+ if (_navigationItems.ElementAtOrDefault(_previousItemId) is {} previousItem)
+ previousItem.IsActive = false;
+
+ item.IsActive = true;
+ Current = item;
+ _previousItemId = itemId;
+
+ if (_pageService is not null)
+ {
+ NavigateByService(item);
+ return;
+ }
+
+ if (item.Cache)
+ {
+ NavigateWithCache(itemId, item, dataContext);
+ return;
+ }
+
+ NavigateWithoutCache(item, dataContext);
+ }
+
+ private void NavigateByService(INavigationItem item)
+ {
+ var instance = _pageService!.GetPage(item.PageType);
+ Guard.IsNotNull(instance, "Page instance");
+
+ _frame.Navigate(instance);
+ }
+
+ private void NavigateWithCache(int itemId, INavigationItem item, object? dataContext)
+ {
+
+ }
+
+ private void NavigateWithoutCache(INavigationItem item, object? dataContext)
+ {
+
+ }
+
+ #endregion
+
+ private int GetItemId(Func prediction)
+ {
+ int selectedIndex = -1;
+
+ for (int i = 0; i < _navigationItems.Length; i++)
+ {
+ if (!prediction.Invoke(_navigationItems[i])) continue;
+
+ selectedIndex = i;
+ break;
+ }
+ return selectedIndex;
}
}
From 449eb02a235eafe5f040fb2859b6ba285fae1645 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 1 Aug 2022 19:56:02 +0600
Subject: [PATCH 03/28] fixed items
---
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 2ebbaa772..ae3ce1471 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -37,14 +37,14 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
///
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(nameof(Items),
typeof(ObservableCollection), typeof(NavigationBase),
- new PropertyMetadata(new ObservableCollection()));
+ new PropertyMetadata(null));
///
/// Property for .
///
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(nameof(Footer),
typeof(ObservableCollection), typeof(NavigationBase),
- new PropertyMetadata(new ObservableCollection()));
+ new PropertyMetadata(null));
///
/// Property for .
@@ -239,6 +239,9 @@ static NavigationBase()
///
protected NavigationBase()
{
+ Items = new ObservableCollection();
+ Footer = new ObservableCollection();
+
// Let the NavigationItem children be able to get me.
NavigationParent = this;
@@ -300,9 +303,7 @@ protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
_navigationManager.Dispose();
foreach (var item in _items)
- {
item.Click -= OnNavigationItemClicked;
- }
}
///
From e85c86810619f69c910dcf22741d6b614c31bb41 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 08:02:40 +0600
Subject: [PATCH 04/28] added navigation stack
---
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 7 +-
.../Common/RoutedNavigationEventArgs.cs | 7 +-
src/Wpf.Ui/Controls/Breadcrumb.cs | 10 +--
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 19 +----
.../Controls/Navigation/NavigationBase.cs | 23 +-----
.../Services/Internal/NavigationManager.cs | 82 ++++++++++++++-----
6 files changed, 81 insertions(+), 67 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 1ef25e160..8c0d0f51c 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -4,6 +4,7 @@
// All Rights Reserved.
using System;
+using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@@ -161,14 +162,16 @@ private void TrayMenuItem_OnClick(object sender, RoutedEventArgs e)
private void RootNavigation_OnNavigated(INavigation sender, RoutedNavigationEventArgs e)
{
- System.Diagnostics.Debug.WriteLine($"DEBUG | WPF UI Navigated to: {sender?.Current ?? null}", "Wpf.Ui.Demo");
+ var current = e.NavigationStack.ElementAt(0);
+
+ System.Diagnostics.Debug.WriteLine($"DEBUG | WPF UI Navigated to: {current}", "Wpf.Ui.Demo");
// This funky solution allows us to impose a negative
// margin for Frame only for the Dashboard page, thanks
// to which the banner will cover the entire page nicely.
RootFrame.Margin = new Thickness(
left: 0,
- top: sender?.Current?.PageTag == "dashboard" ? -69 : 0,
+ top: current.PageTag == "dashboard" ? -69 : 0,
right: 0,
bottom: 0);
}
diff --git a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs b/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
index ae124110c..a6987e081 100644
--- a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
+++ b/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
@@ -3,6 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+using System.Collections.Generic;
using System.Windows;
using Wpf.Ui.Controls.Interfaces;
@@ -16,7 +17,7 @@ public class RoutedNavigationEventArgs : RoutedEventArgs
///
/// Currently displayed page.
///
- public INavigationItem CurrentPage { get; set; }
+ public IEnumerable NavigationStack { get; set; }
///
/// Constructor for .
@@ -24,9 +25,9 @@ public class RoutedNavigationEventArgs : RoutedEventArgs
/// 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(
+ public RoutedNavigationEventArgs(RoutedEvent routedEvent, object source, IEnumerable navigationStack) : base(
routedEvent, source)
{
- CurrentPage = currentPage;
+ NavigationStack = navigationStack;
}
}
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index cb0b089ef..db65c6361 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -4,6 +4,7 @@
// All Rights Reserved.
using System;
+using System.Linq;
using System.Windows;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.Interfaces;
@@ -53,13 +54,12 @@ protected virtual void OnNavigated(INavigation sender, RoutedNavigationEventArgs
#endif
//TODO: Navigate with previous levels
+ //TMP
+ var firstItem = e.NavigationStack.ElementAt(0);
- if (Navigation?.Current is not INavigationItem item)
- return;
-
- var pageName = item.Content as string;
+ var pageName = firstItem.Content as string;
- if (String.IsNullOrEmpty(pageName))
+ if (string.IsNullOrEmpty(pageName))
return;
Current = pageName;
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 24598007c..71f12a507 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -5,6 +5,7 @@
#nullable enable
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Controls;
@@ -36,9 +37,9 @@ public interface INavigation
bool CanGoBack { get; }
///
- /// Currently used item like .
+ /// TODO
///
- INavigationItem Current { get; }
+ IEnumerable NavigationStack { get; }
///
/// Gets or sets the in which the will be loaded after navigation.
@@ -49,13 +50,11 @@ public interface INavigation
///
/// 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; }
///
@@ -69,18 +68,6 @@ public interface INavigation
[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.
///
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index ae3ce1471..d9af2bffa 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -217,8 +217,7 @@ public event RoutedNavigationEvent NavigatedBackward
///
public bool CanGoBack => _navigationManager.CanGoBack;
- ///
- public INavigationItem Current => _navigationManager.Current;
+ public IEnumerable NavigationStack => _navigationManager.NavigationStack;
///
/// Static constructor overriding default properties.
@@ -356,25 +355,7 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
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);
+ var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, NavigationStack);
RaiseEvent(newEvent);
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 1edd9ae4e..a52588bda 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -16,14 +16,13 @@ internal sealed class NavigationManager : IDisposable
private readonly INavigationItem[] _navigationItems;
private readonly FrameworkElement[] _instances;
private readonly List _history = new();
- private readonly List _navigationStack = new();
private readonly IPageService? _pageService;
private bool _isBackwardsNavigated;
- private int _previousItemId = -1;
+ private bool _addToNavigationStack;
public bool CanGoBack => _history.Count > 1;
- public INavigationItem Current { get; private set; } = null!;
+ public readonly List NavigationStack = new();
public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
{
@@ -49,6 +48,10 @@ public void NavigateTo(string tag, object? dataContext = null)
return;
}
+ _addToNavigationStack = tag.Contains("//");
+ if (_addToNavigationStack)
+ tag = tag.Replace("//", string.Empty).Trim();
+
var itemId = GetItemId(item => item.PageTag == tag);
NavigateInternal(itemId, dataContext);
}
@@ -76,9 +79,22 @@ private void NavigateBack()
private void NavigateInternal(int itemId, object? dataContext)
{
- if (ReferenceEquals(Current, _navigationItems.ElementAtOrDefault(itemId)))
+ if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
return;
+ switch (NavigationStack.Count)
+ {
+ case > 0 when NavigationStack[NavigationStack.Count -1] == item:
+ return;
+ case 0:
+ NavigationStack.Add(item);
+ break;
+ }
+
+ AddToNavigationStack(item, false);
+
+ item.IsActive = true;
+
if (_isBackwardsNavigated)
{
_isBackwardsNavigated = false;
@@ -88,36 +104,50 @@ private void NavigateInternal(int itemId, object? dataContext)
_history.Add(itemId);
- PerformNavigation(itemId, dataContext);
+ PerformNavigation((itemId, item), dataContext);
}
- #region PerformNavigation
-
- private void PerformNavigation(int itemId, object? dataContext)
+ private void AddToNavigationStack(INavigationItem item, bool itemIsNotVisible)
{
- if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
- return;
+ if (_addToNavigationStack && !NavigationStack.Contains(item))
+ NavigationStack.Add(item);
- if (_navigationItems.ElementAtOrDefault(_previousItemId) is {} previousItem)
- previousItem.IsActive = false;
+ if (itemIsNotVisible || !_addToNavigationStack)
+ {
+ NavigationStack[0].IsActive = false;
+ NavigationStack[0] = item;
- item.IsActive = true;
- Current = item;
- _previousItemId = itemId;
+ ClearNavigationStack(1);
+ }
+
+ var navigationStackCount = NavigationStack.Count;
+ if (navigationStackCount > 1)
+ {
+ //var navItem = NavigationStack[NavigationStack.Count - 2];
+
+ var index = NavigationStack.IndexOf(item);
+ if (index < navigationStackCount - 1)
+ ClearNavigationStack(++index);
+ }
+ }
+
+ #region PerformNavigation
+ private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
+ {
if (_pageService is not null)
{
- NavigateByService(item);
+ NavigateByService(itemData.item);
return;
}
- if (item.Cache)
+ if (itemData.item.Cache)
{
- NavigateWithCache(itemId, item, dataContext);
+ NavigateWithCache(itemData, dataContext);
return;
}
- NavigateWithoutCache(item, dataContext);
+ NavigateWithoutCache(itemData.item, dataContext);
}
private void NavigateByService(INavigationItem item)
@@ -128,7 +158,7 @@ private void NavigateByService(INavigationItem item)
_frame.Navigate(instance);
}
- private void NavigateWithCache(int itemId, INavigationItem item, object? dataContext)
+ private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
{
}
@@ -140,6 +170,18 @@ private void NavigateWithoutCache(INavigationItem item, object? dataContext)
#endregion
+ private void ClearNavigationStack(int navigationStackItemIndex)
+ {
+ var navigationStackCount = NavigationStack.Count;
+ List buffer = new(navigationStackCount - navigationStackItemIndex);
+
+ for (int i = navigationStackItemIndex; i <= navigationStackCount - 1; i++)
+ buffer.Add(NavigationStack[i]);
+
+ foreach (var item in buffer)
+ NavigationStack.Remove(item);
+ }
+
private int GetItemId(Func prediction)
{
int selectedIndex = -1;
From 8fa6a608df65d4ff7a9478f716c85f6e426e2751 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 08:22:57 +0600
Subject: [PATCH 05/28] a small optimization of the ClearNavigationStack method
---
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index a52588bda..708107c19 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -1,5 +1,6 @@
#nullable enable
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
@@ -17,6 +18,7 @@ internal sealed class NavigationManager : IDisposable
private readonly FrameworkElement[] _instances;
private readonly List _history = new();
private readonly IPageService? _pageService;
+ private readonly ArrayPool _arrayPool = ArrayPool.Create();
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
@@ -173,13 +175,19 @@ private void NavigateWithoutCache(INavigationItem item, object? dataContext)
private void ClearNavigationStack(int navigationStackItemIndex)
{
var navigationStackCount = NavigationStack.Count;
- List buffer = new(navigationStackCount - navigationStackItemIndex);
+ var buffer = _arrayPool.Rent(navigationStackCount - navigationStackItemIndex);
- for (int i = navigationStackItemIndex; i <= navigationStackCount - 1; i++)
- buffer.Add(NavigationStack[i]);
+ int i = 0;
+ for (int j = navigationStackItemIndex; j <= navigationStackCount - 1; j++)
+ {
+ buffer[i] = NavigationStack[j];
+ i++;
+ }
foreach (var item in buffer)
NavigationStack.Remove(item);
+
+ _arrayPool.Return(buffer, true);
}
private int GetItemId(Func prediction)
From ca342a3692915e46f9b87ac2a51a18729db8e7e2 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 09:18:07 +0600
Subject: [PATCH 06/28] added IsHidden property to the INavigationItem
---
src/Wpf.Ui.Demo/App.xaml.cs | 2 +
src/Wpf.Ui.Demo/Views/Container.xaml | 8 ++-
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 25 ++++-----
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 5 ++
.../Controls/Interfaces/INavigationItem.cs | 5 ++
.../Controls/Navigation/NavigationBase.cs | 54 +++++++++++++------
src/Wpf.Ui/Controls/NavigationItem.cs | 3 ++
.../Services/Internal/NavigationManager.cs | 13 +++--
8 files changed, 78 insertions(+), 37 deletions(-)
diff --git a/src/Wpf.Ui.Demo/App.xaml.cs b/src/Wpf.Ui.Demo/App.xaml.cs
index 0fba0c658..9a23ac79d 100644
--- a/src/Wpf.Ui.Demo/App.xaml.cs
+++ b/src/Wpf.Ui.Demo/App.xaml.cs
@@ -94,6 +94,8 @@ public partial class App
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
+
// Test windows
services.AddTransient();
services.AddTransient();
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index aaf32c924..0df798af1 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -98,6 +98,12 @@
Content="Theme"
Icon="DarkTheme24" />
+
+
+
@@ -198,8 +204,8 @@
ForceShutdown="False"
Icon="pack://application:,,,/Resources/wpfui.png"
MinimizeToTray="False"
- ShowHelp="False"
ShowClose="True"
+ ShowHelp="False"
ShowMaximize="True"
ShowMinimize="True"
UseSnapLayout="True">
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 8c0d0f51c..2ed59a27b 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -115,7 +115,7 @@ public void CloseWindow()
#endregion INavigationWindow methods
- private void InvokeSplashScreen()
+ private async void InvokeSplashScreen()
{
if (_initialized)
return;
@@ -127,24 +127,17 @@ private void InvokeSplashScreen()
_taskBarService.SetState(this, TaskBarProgressState.Indeterminate);
- Task.Run(async () =>
- {
- // Remember to always include Delays and Sleeps in
- // your applications to be able to charge the client for optimizations later.
- await Task.Delay(4000);
+ // Remember to always include Delays and Sleeps in
+ // your applications to be able to charge the client for optimizations later.
+ await Task.Delay(4000);
- await Dispatcher.InvokeAsync(() =>
- {
- RootWelcomeGrid.Visibility = Visibility.Hidden;
- RootMainGrid.Visibility = Visibility.Visible;
+ RootWelcomeGrid.Visibility = Visibility.Hidden;
+ RootMainGrid.Visibility = Visibility.Visible;
- NavigateTo(typeof(Pages.Dashboard));
+ NavigateTo(typeof(Pages.Dashboard));
+ NavigateTo("//test");
- _taskBarService.SetState(this, TaskBarProgressState.None);
- });
-
- return true;
- });
+ _taskBarService.SetState(this, TaskBarProgressState.None);
}
private void NavigationButtonTheme_OnClick(object sender, RoutedEventArgs e)
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 71f12a507..14bd4ad3a 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -57,6 +57,11 @@ public interface INavigation
///
ObservableCollection Footer { get; set; }
+ ///
+ /// TODO
+ ///
+ List HiddenItems { get; set; }
+
///
/// Specifies dimension of children stacking.
///
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
index 216171173..c571d82ce 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
@@ -55,4 +55,9 @@ public interface INavigationItem
///
[Category("Behavior")]
event RoutedEventHandler Click;
+
+ ///
+ /// TODO
+ ///
+ internal bool IsHidden { get; set; }
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index d9af2bffa..47951d42a 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -46,6 +46,13 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
typeof(ObservableCollection), typeof(NavigationBase),
new PropertyMetadata(null));
+ ///
+ /// Property for .
+ ///
+ public static readonly DependencyProperty HiddenItemsProperty = DependencyProperty.Register(nameof(HiddenItems),
+ typeof(List), typeof(NavigationBase),
+ new PropertyMetadata(null));
+
///
/// Property for .
///
@@ -107,17 +114,24 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
///
public ObservableCollection Items
{
- get => (GetValue(ItemsProperty) as ObservableCollection)!;
+ get => (ObservableCollection) GetValue(ItemsProperty);
set => SetValue(ItemsProperty, value);
}
///
public ObservableCollection Footer
{
- get => (GetValue(FooterProperty) as ObservableCollection)!;
+ get => (ObservableCollection) GetValue(FooterProperty);
set => SetValue(FooterProperty, value);
}
+ ///
+ public List HiddenItems
+ {
+ get => (List) GetValue(HiddenItemsProperty);
+ set => SetValue(HiddenItemsProperty, value);
+ }
+
///
[Obsolete("Work in progress.")]
public Orientation Orientation
@@ -240,6 +254,7 @@ protected NavigationBase()
{
Items = new ObservableCollection();
Footer = new ObservableCollection();
+ HiddenItems = new List();
// Let the NavigationItem children be able to get me.
NavigationParent = this;
@@ -284,7 +299,7 @@ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
Guard.IsNotNull(Frame, nameof(Frame));
- _items = MergeItems(Items, Footer);
+ _items = MergeItems();
_frameManager = new FrameManager(Frame, TransitionDuration, TransitionType);
_navigationManager = new NavigationManager(Frame, _pageService, _items);
@@ -400,27 +415,34 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
return (NavigationBase?)navigationItem.GetValue(NavigationParentProperty);
}
- private INavigationItem[] MergeItems(IReadOnlyList items, IReadOnlyList footer)
+ private INavigationItem[] MergeItems()
{
- var overallCount = items.Count + footer.Count;
- List overallItems = new List();
+ var overallCount = Items.Count + Footer.Count + HiddenItems.Count;
+ INavigationItem[] buffer = new INavigationItem[overallCount - 1];
+ int i = 0;
+
+ AddToBufferList(Items);
+ AddToBufferList(Footer);
+ AddToBufferList(HiddenItems, item => item.IsHidden = true);
+
+ return buffer;
- foreach (var addedItem in items)
+ void AddToBufferList(IEnumerable list, Action? action = null)
{
- if (addedItem is not INavigationItem item) continue;
+ foreach (var addedItem in list)
+ {
+ if (addedItem is not INavigationItem item) continue;
- item.Click += OnNavigationItemClicked;
- overallItems.Add(item);
+ action?.Invoke(item);
+ AddToBuffer(item);
+ }
}
- foreach (var addedItem in footer)
+ void AddToBuffer(INavigationItem item)
{
- if (addedItem is not INavigationItem item) continue;
-
item.Click += OnNavigationItemClicked;
- overallItems.Add(item);
+ buffer[i] = item;
+ i++;
}
-
- return overallItems.ToArray();
}
}
diff --git a/src/Wpf.Ui/Controls/NavigationItem.cs b/src/Wpf.Ui/Controls/NavigationItem.cs
index 496a57364..95ab1cbe3 100644
--- a/src/Wpf.Ui/Controls/NavigationItem.cs
+++ b/src/Wpf.Ui/Controls/NavigationItem.cs
@@ -237,6 +237,9 @@ protected virtual Uri BaseUri
set => SetValue(BaseUriHelper.BaseUriProperty, value);
}
+ ///
+ bool INavigationItem.IsHidden { get; set; }
+
///
protected override void OnContentChanged(object oldContent, object newContent)
{
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 708107c19..0ea72e745 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -55,6 +55,9 @@ public void NavigateTo(string tag, object? dataContext = null)
tag = tag.Replace("//", string.Empty).Trim();
var itemId = GetItemId(item => item.PageTag == tag);
+ if (itemId < 0)
+ ThrowHelper.ThrowArgumentException($"Item with: {tag} tag not found");
+
NavigateInternal(itemId, dataContext);
}
@@ -93,7 +96,7 @@ private void NavigateInternal(int itemId, object? dataContext)
break;
}
- AddToNavigationStack(item, false);
+ AddToNavigationStack(item);
item.IsActive = true;
@@ -109,12 +112,12 @@ private void NavigateInternal(int itemId, object? dataContext)
PerformNavigation((itemId, item), dataContext);
}
- private void AddToNavigationStack(INavigationItem item, bool itemIsNotVisible)
+ private void AddToNavigationStack(INavigationItem item)
{
if (_addToNavigationStack && !NavigationStack.Contains(item))
NavigationStack.Add(item);
- if (itemIsNotVisible || !_addToNavigationStack)
+ if (!item.IsHidden || !_addToNavigationStack)
{
NavigationStack[0].IsActive = false;
NavigationStack[0] = item;
@@ -125,7 +128,9 @@ private void AddToNavigationStack(INavigationItem item, bool itemIsNotVisible)
var navigationStackCount = NavigationStack.Count;
if (navigationStackCount > 1)
{
- //var navItem = NavigationStack[NavigationStack.Count - 2];
+ var navItem = NavigationStack[NavigationStack.Count - 2];
+ if (navItem.IsHidden)
+ navItem.IsActive = false;
var index = NavigationStack.IndexOf(item);
if (index < navigationStackCount - 1)
From 98d70ad83c61e3acc3badf985a634cb92fcedb7f Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 16:18:26 +0600
Subject: [PATCH 07/28] implemented dynamic breadcrumb
---
src/Wpf.Ui.Demo/App.xaml.cs | 1 +
src/Wpf.Ui.Demo/Views/Container.xaml | 6 +-
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 1 +
src/Wpf.Ui/Controls/Breadcrumb.cs | 80 ++++++++-------
src/Wpf.Ui/Controls/BreadcrumbItem.cs | 43 ++++++++
src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml | 58 ++---------
.../Styles/Controls/BreadcrumbItem.xaml | 97 +++++++++++++++++++
src/Wpf.Ui/Styles/Wpf.Ui.xaml | 1 +
8 files changed, 198 insertions(+), 89 deletions(-)
create mode 100644 src/Wpf.Ui/Controls/BreadcrumbItem.cs
create mode 100644 src/Wpf.Ui/Styles/Controls/BreadcrumbItem.xaml
diff --git a/src/Wpf.Ui.Demo/App.xaml.cs b/src/Wpf.Ui.Demo/App.xaml.cs
index 9a23ac79d..a4ad04789 100644
--- a/src/Wpf.Ui.Demo/App.xaml.cs
+++ b/src/Wpf.Ui.Demo/App.xaml.cs
@@ -95,6 +95,7 @@ public partial class App
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
// Test windows
services.AddTransient();
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index 0df798af1..7a8c2cd76 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -99,10 +99,8 @@
Icon="DarkTheme24" />
-
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 2ed59a27b..125ecce23 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -136,6 +136,7 @@ private async void InvokeSplashScreen()
NavigateTo(typeof(Pages.Dashboard));
NavigateTo("//test");
+ NavigateTo("//test2");
_taskBarService.SetState(this, TaskBarProgressState.None);
}
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index db65c6361..42f3e9339 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -3,9 +3,10 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
-using System;
-using System.Linq;
+using System.Collections.ObjectModel;
using System.Windows;
+using System.Windows.Input;
+using Microsoft.Toolkit.Diagnostics;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.Interfaces;
@@ -16,27 +17,16 @@ namespace Wpf.Ui.Controls;
///
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));
+ new PropertyMetadata(null));
+
+ public static readonly DependencyProperty BreadcrumbItemsProperty = DependencyProperty.Register(nameof(BreadcrumbItems),
+ typeof(ObservableCollection), typeof(Breadcrumb), new PropertyMetadata(null));
- ///
- /// based on which displays the titles.
- ///
- public string Current
- {
- get => (string)GetValue(CurrentProperty);
- set => SetValue(CurrentProperty, value);
- }
///
/// based on which displays the titles.
@@ -47,34 +37,56 @@ public INavigation Navigation
set => SetValue(NavigationProperty, value);
}
- protected virtual void OnNavigated(INavigation sender, RoutedNavigationEventArgs e)
+ public ObservableCollection BreadcrumbItems
{
-#if DEBUG
- System.Diagnostics.Debug.WriteLine($"INFO | {typeof(Breadcrumb)} builded, current nav: {Navigation.GetType()}", "Wpf.Ui.Breadcrumb");
-#endif
+ get => (ObservableCollection)GetValue(BreadcrumbItemsProperty);
+ private set => SetValue(BreadcrumbItemsProperty, value);
+ }
- //TODO: Navigate with previous levels
- //TMP
- var firstItem = e.NavigationStack.ElementAt(0);
+ private readonly ICommand _onClickCommand;
- var pageName = firstItem.Content as string;
+ public Breadcrumb()
+ {
+ BreadcrumbItems = new ObservableCollection();
+ _onClickCommand = new RelayCommand(OnClick);
- if (string.IsNullOrEmpty(pageName))
- return;
+ Loaded += (sender, args) =>
+ {
+ Guard.IsNotNull(Navigation, nameof(Navigation));
+ Navigation.Navigated += OnNavigated;
+ };
- Current = pageName;
+ Unloaded += (sender, args) =>
+ {
+ Navigation.Navigated -= OnNavigated;
+ };
}
- protected virtual void OnNavigationChanged()
+ protected virtual void OnNavigated(INavigation sender, RoutedNavigationEventArgs e)
{
- Navigation.Navigated += OnNavigated;
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine($"INFO | {typeof(Breadcrumb)} builded, current nav: {Navigation.GetType()}", "Wpf.Ui.Breadcrumb");
+#endif
+
+ //TODO This event needs some kind of optimization
+ BreadcrumbItems.Clear();
+ foreach (var navigationItem in e.NavigationStack)
+ {
+ BreadcrumbItems.Add(new BreadcrumbItem()
+ {
+ Text = navigationItem.Content as string ?? string.Empty,
+ PageTag = navigationItem.PageTag,
+ OnClickCommand = _onClickCommand
+ });
+ }
+
+ BreadcrumbItems[BreadcrumbItems.Count - 1].IsActive = true;
}
- private static void OnNavigationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ private void OnClick(object obj)
{
- if (d is not Breadcrumb breadcrumb)
- return;
+ var pageTag = (string)obj;
- breadcrumb.OnNavigationChanged();
+ Navigation.NavigateTo(pageTag);
}
}
diff --git a/src/Wpf.Ui/Controls/BreadcrumbItem.cs b/src/Wpf.Ui/Controls/BreadcrumbItem.cs
new file mode 100644
index 000000000..3ef634d90
--- /dev/null
+++ b/src/Wpf.Ui/Controls/BreadcrumbItem.cs
@@ -0,0 +1,43 @@
+using System.Windows;
+using System.Windows.Input;
+
+namespace Wpf.Ui.Controls;
+
+public class BreadcrumbItem : System.Windows.Controls.Control
+{
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text),
+ typeof(string), typeof(BreadcrumbItem), new PropertyMetadata(string.Empty));
+
+ public static readonly DependencyProperty PageTagProperty = DependencyProperty.Register(nameof(PageTag),
+ typeof(string), typeof(BreadcrumbItem), new PropertyMetadata(string.Empty));
+
+ public static readonly DependencyProperty OnClickCommandProperty = DependencyProperty.Register(nameof(OnClickCommand),
+ typeof(ICommand), typeof(BreadcrumbItem), new PropertyMetadata(null));
+
+ public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(nameof(IsActive),
+ typeof(bool), typeof(BreadcrumbItem), new PropertyMetadata(false));
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+ set => SetValue(TextProperty, value);
+ }
+
+ public string PageTag
+ {
+ get => (string)GetValue(PageTagProperty);
+ set => SetValue(PageTagProperty, value);
+ }
+
+ public ICommand OnClickCommand
+ {
+ get => (ICommand)GetValue(OnClickCommandProperty);
+ set => SetValue(OnClickCommandProperty, value);
+ }
+
+ public bool IsActive
+ {
+ get => (bool)GetValue(IsActiveProperty);
+ set => SetValue(IsActiveProperty, value);
+ }
+}
diff --git a/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml b/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml
index df9936ef6..57d4846b3 100644
--- a/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml
+++ b/src/Wpf.Ui/Styles/Controls/Breadcrumb.xaml
@@ -10,8 +10,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Wpf.Ui.Controls">
-
-
+
+
+
+
\ 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..81c6fd434 100644
--- a/src/Wpf.Ui/Styles/Wpf.Ui.xaml
+++ b/src/Wpf.Ui/Styles/Wpf.Ui.xaml
@@ -33,6 +33,7 @@
+
From a78569cb05b692e561d33ff2a1322d2d5c9574bf Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 16:25:36 +0600
Subject: [PATCH 08/28] navigation with previous levels works
---
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 0ea72e745..b684dac36 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -117,7 +117,7 @@ private void AddToNavigationStack(INavigationItem item)
if (_addToNavigationStack && !NavigationStack.Contains(item))
NavigationStack.Add(item);
- if (!item.IsHidden || !_addToNavigationStack)
+ if (!item.IsHidden && !_addToNavigationStack)
{
NavigationStack[0].IsActive = false;
NavigationStack[0] = item;
From f1148cf9f2ff5cdac5009fa2ff0829eaf72dfe46 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 16:55:03 +0600
Subject: [PATCH 09/28] small breadcrumb optimization
---
src/Wpf.Ui/Controls/Breadcrumb.cs | 40 ++++++++++++++-----
src/Wpf.Ui/Controls/BreadcrumbItem.cs | 8 ++++
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 2 +-
.../Controls/Navigation/NavigationBase.cs | 2 +-
.../Services/Internal/NavigationManager.cs | 3 +-
5 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index 42f3e9339..aefc8557f 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -4,6 +4,7 @@
// All Rights Reserved.
using System.Collections.ObjectModel;
+using System.Collections.Specialized;
using System.Windows;
using System.Windows.Input;
using Microsoft.Toolkit.Diagnostics;
@@ -50,15 +51,18 @@ public Breadcrumb()
BreadcrumbItems = new ObservableCollection();
_onClickCommand = new RelayCommand(OnClick);
- Loaded += (sender, args) =>
+ Loaded += (_, _) =>
{
Guard.IsNotNull(Navigation, nameof(Navigation));
+
Navigation.Navigated += OnNavigated;
+ Navigation.NavigationStack.CollectionChanged += NavigationStackOnCollectionChanged;
};
- Unloaded += (sender, args) =>
+ Unloaded += (_, _) =>
{
Navigation.Navigated -= OnNavigated;
+ Navigation.NavigationStack.CollectionChanged -= NavigationStackOnCollectionChanged;
};
}
@@ -67,19 +71,35 @@ protected virtual void OnNavigated(INavigation sender, RoutedNavigationEventArgs
#if DEBUG
System.Diagnostics.Debug.WriteLine($"INFO | {typeof(Breadcrumb)} builded, current nav: {Navigation.GetType()}", "Wpf.Ui.Breadcrumb");
#endif
+ }
- //TODO This event needs some kind of optimization
- BreadcrumbItems.Clear();
- foreach (var navigationItem in e.NavigationStack)
+ private void NavigationStackOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ switch (e.Action)
{
- BreadcrumbItems.Add(new BreadcrumbItem()
+ case NotifyCollectionChangedAction.Add:
{
- Text = navigationItem.Content as string ?? string.Empty,
- PageTag = navigationItem.PageTag,
- OnClickCommand = _onClickCommand
- });
+ foreach (NavigationItem item in e.NewItems!)
+ {
+ BreadcrumbItems.Add(BreadcrumbItem.Create(item, _onClickCommand));
+ }
+
+ break;
+ }
+ case NotifyCollectionChangedAction.Remove:
+ BreadcrumbItems.RemoveAt(e.OldStartingIndex);
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ var replaceItem = (INavigationItem) e.NewItems![0];
+ BreadcrumbItems[0] = BreadcrumbItem.Create(replaceItem, _onClickCommand);
+ break;
+ default:
+ return;
}
+ if (BreadcrumbItems.Count > 1)
+ BreadcrumbItems[BreadcrumbItems.Count - 2].IsActive = false;
+
BreadcrumbItems[BreadcrumbItems.Count - 1].IsActive = true;
}
diff --git a/src/Wpf.Ui/Controls/BreadcrumbItem.cs b/src/Wpf.Ui/Controls/BreadcrumbItem.cs
index 3ef634d90..48a5cf507 100644
--- a/src/Wpf.Ui/Controls/BreadcrumbItem.cs
+++ b/src/Wpf.Ui/Controls/BreadcrumbItem.cs
@@ -1,5 +1,6 @@
using System.Windows;
using System.Windows.Input;
+using Wpf.Ui.Controls.Interfaces;
namespace Wpf.Ui.Controls;
@@ -40,4 +41,11 @@ public bool IsActive
get => (bool)GetValue(IsActiveProperty);
set => SetValue(IsActiveProperty, value);
}
+
+ public static BreadcrumbItem Create(INavigationItem item, ICommand onClickCommand) => new BreadcrumbItem()
+ {
+ Text = item.Content as string ?? string.Empty,
+ PageTag = item.PageTag,
+ OnClickCommand = onClickCommand
+ };
}
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 14bd4ad3a..09ffd1b8c 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -39,7 +39,7 @@ public interface INavigation
///
/// TODO
///
- IEnumerable NavigationStack { get; }
+ ObservableCollection NavigationStack { get; }
///
/// Gets or sets the in which the will be loaded after navigation.
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 47951d42a..1f142f8e8 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -231,7 +231,7 @@ public event RoutedNavigationEvent NavigatedBackward
///
public bool CanGoBack => _navigationManager.CanGoBack;
- public IEnumerable NavigationStack => _navigationManager.NavigationStack;
+ public ObservableCollection NavigationStack => _navigationManager.NavigationStack;
///
/// Static constructor overriding default properties.
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index b684dac36..51cb731fb 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -2,6 +2,7 @@
using System;
using System.Buffers;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@@ -24,7 +25,7 @@ internal sealed class NavigationManager : IDisposable
private bool _addToNavigationStack;
public bool CanGoBack => _history.Count > 1;
- public readonly List NavigationStack = new();
+ public readonly ObservableCollection NavigationStack = new();
public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
{
From e8b4b48f430736f0eb3975bd23f642612bcca0ff Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 17:23:27 +0600
Subject: [PATCH 10/28] transition can be changed dynamically
---
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 9 +++++++--
src/Wpf.Ui/Services/Internal/FrameManager.cs | 13 +++++++------
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 3 +++
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 1f142f8e8..ab027be21 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -29,6 +29,7 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
private NavigationManager _navigationManager = null!;
private IPageService? _pageService;
private INavigationItem[] _items = null!;
+ private bool _loaded;
#region DependencyProperties
@@ -309,6 +310,8 @@ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
_navigationManager.NavigateTo(SelectedPageIndex);
OnNavigated();
}
+
+ _loaded = true;
}
protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
@@ -393,7 +396,8 @@ private static void OnTransitionDurationChanged(DependencyObject d, DependencyPr
if (d is not NavigationBase navigation)
return;
- //navigation._navigationService.TransitionDuration = (int)e.NewValue;
+ if (navigation._loaded)
+ navigation._frameManager.TransitionDuration = (int)e.NewValue;
}
private static void OnTransitionTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -401,7 +405,8 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
if (d is not NavigationBase navigation)
return;
- //navigation._navigationService.TransitionType = (Animations.TransitionType)e.NewValue;
+ if (navigation._loaded)
+ navigation._frameManager.TransitionType = (Animations.TransitionType)e.NewValue;
}
///
diff --git a/src/Wpf.Ui/Services/Internal/FrameManager.cs b/src/Wpf.Ui/Services/Internal/FrameManager.cs
index 179d9def7..d2fce91e0 100644
--- a/src/Wpf.Ui/Services/Internal/FrameManager.cs
+++ b/src/Wpf.Ui/Services/Internal/FrameManager.cs
@@ -11,14 +11,15 @@ namespace Wpf.Ui.Services.Internal;
internal sealed class FrameManager : IDisposable
{
private readonly Frame _frame;
- private readonly int _transitionDuration;
- private readonly TransitionType _transitionType;
+
+ public int TransitionDuration { get; set; }
+ public TransitionType TransitionType { get; set; }
public FrameManager(Frame frame, int transitionDuration, TransitionType transitionType)
{
_frame = frame;
- _transitionDuration = transitionDuration;
- _transitionType = transitionType;
+ TransitionDuration = transitionDuration;
+ TransitionType = transitionType;
_frame.NavigationUIVisibility = NavigationUIVisibility.Hidden;
@@ -41,8 +42,8 @@ private void OnFrameNavigated(object sender, NavigationEventArgs e)
{
_frame.NavigationService.RemoveBackEntry();
- if (_transitionDuration > 0 && e.Content != null)
- Transitions.ApplyTransition(e.Content, _transitionType, _transitionDuration);
+ if (TransitionDuration > 0 && e.Content != null)
+ Transitions.ApplyTransition(e.Content, TransitionType, TransitionDuration);
//TODO
/*// Finally, the navigation took place internally,
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 51cb731fb..534aac170 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -65,6 +65,9 @@ public void NavigateTo(string tag, object? dataContext = null)
public void NavigateTo(Type type, object? dataContext = null)
{
var itemId = GetItemId(serviceItem => serviceItem.PageType == type);
+ if (itemId < 0)
+ ThrowHelper.ThrowArgumentException($"Item with: {type} type not found");
+
NavigateInternal(itemId, dataContext);
}
From b7bd7993fada9d087acb34de0be5e314bc1786fc Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 17:29:36 +0600
Subject: [PATCH 11/28] fixed designer
---
src/Wpf.Ui/Controls/Breadcrumb.cs | 4 ++++
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 7 +++----
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index aefc8557f..12653684a 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -5,6 +5,7 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
+using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using Microsoft.Toolkit.Diagnostics;
@@ -51,6 +52,9 @@ public Breadcrumb()
BreadcrumbItems = new ObservableCollection();
_onClickCommand = new RelayCommand(OnClick);
+ if (DesignerProperties.GetIsInDesignMode(this))
+ return;
+
Loaded += (_, _) =>
{
Guard.IsNotNull(Navigation, nameof(Navigation));
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index ab027be21..43cfdb68a 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -260,7 +260,9 @@ protected NavigationBase()
// Let the NavigationItem children be able to get me.
NavigationParent = this;
- // Loaded does not have override
+ if (DesignerProperties.GetIsInDesignMode(this))
+ return;
+
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
@@ -295,9 +297,6 @@ public void NavigateTo(Type type, object? dataContext = null)
///
protected virtual void OnLoaded(object sender, RoutedEventArgs e)
{
- if (DesignerProperties.GetIsInDesignMode(this))
- return;
-
Guard.IsNotNull(Frame, nameof(Frame));
_items = MergeItems();
From e101be1dde97a8f5d3a2050f537d507d52a82a50 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 18:57:59 +0600
Subject: [PATCH 12/28] implemented navigation without di
---
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 2 +-
src/Wpf.Ui.SimpleDemo/MainWindow.xaml | 20 ++++--
.../Common/RoutedNavigationEventArgs.cs | 9 +--
.../Controls/Interfaces/INavigationItem.cs | 5 +-
.../Controls/Navigation/NavigationBase.cs | 31 ++++------
.../Services/Internal/NavigationManager.cs | 62 +++++++++++++++++--
6 files changed, 90 insertions(+), 39 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 125ecce23..92430ad2a 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -156,7 +156,7 @@ private void TrayMenuItem_OnClick(object sender, RoutedEventArgs e)
private void RootNavigation_OnNavigated(INavigation sender, RoutedNavigationEventArgs e)
{
- var current = e.NavigationStack.ElementAt(0);
+ var current = sender.NavigationStack[sender.NavigationStack.Count - 1];
System.Diagnostics.Debug.WriteLine($"DEBUG | WPF UI Navigated to: {current}", "Wpf.Ui.Demo");
diff --git a/src/Wpf.Ui.SimpleDemo/MainWindow.xaml b/src/Wpf.Ui.SimpleDemo/MainWindow.xaml
index 9e4f5fe78..2a82b0442 100644
--- a/src/Wpf.Ui.SimpleDemo/MainWindow.xaml
+++ b/src/Wpf.Ui.SimpleDemo/MainWindow.xaml
@@ -29,12 +29,24 @@
Icon="Home24"
PageTag="home"
PageType="{x:Type local:DashboardPage}" />
-
-
+
+
-
-
+
+
public class RoutedNavigationEventArgs : RoutedEventArgs
{
- ///
- /// Currently displayed page.
- ///
- public IEnumerable NavigationStack { 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, IEnumerable navigationStack) : base(
+ public RoutedNavigationEventArgs(RoutedEvent routedEvent, object source) : base(
routedEvent, source)
{
- NavigationStack = navigationStack;
+
}
}
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
index c571d82ce..e9ab5fe1b 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
@@ -3,6 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+#nullable enable
using System;
using System.ComponentModel;
using System.Windows;
@@ -43,12 +44,12 @@ public interface INavigationItem
///
/// A inherited from that defines page of the item.
///
- Type PageType { get; set; }
+ Type? PageType { get; set; }
///
/// Absolute path to the XAML template based on and .
///
- Uri AbsolutePageSource { get; }
+ Uri? AbsolutePageSource { get; }
///
/// Add / Remove ClickEvent handler
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 43cfdb68a..8dfaed087 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -372,7 +372,7 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
protected virtual void OnNavigated()
{
- var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, NavigationStack);
+ var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this);
RaiseEvent(newEvent);
}
@@ -384,9 +384,6 @@ protected virtual void OnNavigationItemClicked(object sender, RoutedEventArgs e)
if (sender is not INavigationItem navigationItem)
return;
- if (navigationItem.AbsolutePageSource == null && navigationItem.PageType == null)
- return;
-
NavigateTo(navigationItem.PageTag);
}
@@ -421,32 +418,26 @@ private static void OnTransitionTypeChanged(DependencyObject d, DependencyProper
private INavigationItem[] MergeItems()
{
- var overallCount = Items.Count + Footer.Count + HiddenItems.Count;
- INavigationItem[] buffer = new INavigationItem[overallCount - 1];
- int i = 0;
+ List buffer = new List(Items.Count);
- AddToBufferList(Items);
- AddToBufferList(Footer);
- AddToBufferList(HiddenItems, item => item.IsHidden = true);
+ AddToBuffer(Items);
+ AddToBuffer(Footer);
+ AddToBuffer(HiddenItems, item => item.IsHidden = true);
- return buffer;
+ return buffer.ToArray();
- void AddToBufferList(IEnumerable list, Action? action = null)
+ void AddToBuffer(IEnumerable list, Action? action = null)
{
foreach (var addedItem in list)
{
if (addedItem is not INavigationItem item) continue;
+ if (item.PageType is not null)
+ item.Click += OnNavigationItemClicked;
+
action?.Invoke(item);
- AddToBuffer(item);
+ buffer.Add(item);
}
}
-
- void AddToBuffer(INavigationItem item)
- {
- item.Click += OnNavigationItemClicked;
- buffer[i] = item;
- i++;
- }
}
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 534aac170..6c6aa6b7e 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -16,7 +16,7 @@ internal sealed class NavigationManager : IDisposable
{
private readonly Frame _frame;
private readonly INavigationItem[] _navigationItems;
- private readonly FrameworkElement[] _instances;
+ private readonly FrameworkElement?[] _instances;
private readonly List _history = new();
private readonly IPageService? _pageService;
private readonly ArrayPool _arrayPool = ArrayPool.Create();
@@ -76,6 +76,8 @@ public void NavigateTo(int id, object? dataContext = null)
NavigateInternal(id, dataContext);
}
+ #region NavigationInternal
+
private void NavigateBack()
{
if (_history.Count <= 1)
@@ -142,13 +144,15 @@ private void AddToNavigationStack(INavigationItem item)
}
}
+ #endregion
+
#region PerformNavigation
private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
{
if (_pageService is not null)
{
- NavigateByService(itemData.item);
+ NavigateByService(itemData);
return;
}
@@ -161,9 +165,17 @@ private void PerformNavigation((int itemId, INavigationItem item) itemData, obje
NavigateWithoutCache(itemData.item, dataContext);
}
- private void NavigateByService(INavigationItem item)
+ private void NavigateByService((int itemId, INavigationItem item) itemData)
{
- var instance = _pageService!.GetPage(item.PageType);
+ if (itemData.item.PageType is null)
+ return;
+
+ if (_instances[itemData.itemId] is not null)
+ {
+ //TODO
+ }
+
+ var instance = _pageService!.GetPage(itemData.item.PageType);
Guard.IsNotNull(instance, "Page instance");
_frame.Navigate(instance);
@@ -171,16 +183,54 @@ private void NavigateByService(INavigationItem item)
private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
{
+ if (_instances[itemData.itemId] is null)
+ {
+ _instances[itemData.itemId] = NavigateWithoutCache(itemData.item, dataContext);
+ return;
+ }
+
+ var instance = _instances[itemData.itemId]!;
+
+ if (dataContext is not null)
+ instance.DataContext = dataContext;
+ _frame.Navigate(instance);
+
+#if DEBUG
+ System.Diagnostics.Debug.WriteLine(
+ $"DEBUG | {itemData.item.PageTag} navigated internally, with cache by it's instance.");
+#endif
}
- private void NavigateWithoutCache(INavigationItem item, object? dataContext)
+ private FrameworkElement? NavigateWithoutCache(INavigationItem item, object? dataContext)
{
+ FrameworkElement? instance = null;
+
+ if (item.PageType is not null)
+ {
+ instance = NavigationServiceActivator.CreateInstance(item.PageType, dataContext);
+ _frame.Navigate(instance);
+ }
+
+ if (item.AbsolutePageSource is not null)
+ {
+ _frame.Navigate(item.AbsolutePageSource);
+ }
+
+#if DEBUG
+ string navigationType = item.PageType is not null ? "type" : "source";
+
+ System.Diagnostics.Debug.WriteLine(
+ $"DEBUG | {item.PageTag} navigated internally, without cache by it's {navigationType}.");
+#endif
+ return instance;
}
#endregion
+ #region PrivateMethods
+
private void ClearNavigationStack(int navigationStackItemIndex)
{
var navigationStackCount = NavigationStack.Count;
@@ -213,4 +263,6 @@ private int GetItemId(Func prediction)
return selectedIndex;
}
+
+ #endregion
}
From fe6d8a1e312251ec1e306480f9a481361ece1e2b Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 18:58:51 +0600
Subject: [PATCH 13/28] breadcrumb loading fix
---
src/Wpf.Ui/Controls/Breadcrumb.cs | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index 12653684a..0d4cd7fce 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -58,36 +58,31 @@ public Breadcrumb()
Loaded += (_, _) =>
{
Guard.IsNotNull(Navigation, nameof(Navigation));
-
- Navigation.Navigated += OnNavigated;
Navigation.NavigationStack.CollectionChanged += NavigationStackOnCollectionChanged;
+
+ if (Navigation.NavigationStack.Count <= 0)
+ return;
+
+ foreach (var item in Navigation.NavigationStack)
+ BreadcrumbItems.Add( BreadcrumbItem.Create(item, _onClickCommand));
+
+ BreadcrumbItems[BreadcrumbItems.Count - 1].IsActive = true;
};
Unloaded += (_, _) =>
{
- Navigation.Navigated -= OnNavigated;
Navigation.NavigationStack.CollectionChanged -= NavigationStackOnCollectionChanged;
};
}
- 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
- }
-
private void NavigationStackOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
{
- foreach (NavigationItem item in e.NewItems!)
- {
- BreadcrumbItems.Add(BreadcrumbItem.Create(item, _onClickCommand));
- }
-
+ var newItem = (INavigationItem) e.NewItems![0];
+ BreadcrumbItems.Add(BreadcrumbItem.Create(newItem, _onClickCommand));
break;
}
case NotifyCollectionChangedAction.Remove:
@@ -95,7 +90,9 @@ private void NavigationStackOnCollectionChanged(object sender, NotifyCollectionC
break;
case NotifyCollectionChangedAction.Replace:
var replaceItem = (INavigationItem) e.NewItems![0];
- BreadcrumbItems[0] = BreadcrumbItem.Create(replaceItem, _onClickCommand);
+ var breadcrumbItem = BreadcrumbItem.Create(replaceItem, _onClickCommand);
+
+ BreadcrumbItems[0] = breadcrumbItem;
break;
default:
return;
@@ -105,6 +102,7 @@ private void NavigationStackOnCollectionChanged(object sender, NotifyCollectionC
BreadcrumbItems[BreadcrumbItems.Count - 2].IsActive = false;
BreadcrumbItems[BreadcrumbItems.Count - 1].IsActive = true;
+
}
private void OnClick(object obj)
From 5c7acfe456e9e0e4b204329a39c732233e6a94d4 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 2 Aug 2022 19:13:58 +0600
Subject: [PATCH 14/28] implemented ClearCache
---
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 5 +++++
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 7 +++----
.../Services/Internal/NavigationManager.cs | 16 ++++++++++++++++
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 09ffd1b8c..1eeb093aa 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -91,6 +91,11 @@ public interface INavigation
///
void SetIPageService(IPageService pageService);
+ ///
+ ///
+ ///
+ void Preload();
+
///
/// Clears all initialized instances of the pages.
///
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 8dfaed087..67043b777 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -272,11 +272,10 @@ public void SetIPageService(IPageService pageService)
_pageService = pageService;
}
+ public void Preload() => _navigationManager.Preload();
+
///
- public void ClearCache()
- {
-
- }
+ public void ClearCache() => _navigationManager.ClearCache();
///
public void NavigateTo(string pageTag, object? dataContext = null)
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 6c6aa6b7e..1f6e9ace7 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -41,6 +41,22 @@ public void Dispose()
}
+ public void Preload()
+ {
+ //Why URI
+ //Application.LoadComponent()
+
+ ThrowHelper.ThrowNotSupportedException("Preloading currently not supported");
+ }
+
+ public void ClearCache()
+ {
+ for (int i = 0; i < _instances.Length; i++)
+ {
+ _instances[i] = null;
+ }
+ }
+
public void NavigateTo(string tag, object? dataContext = null)
{
Guard.IsNotNullOrEmpty(tag, nameof(tag));
From 0032c6e973ccbdc6f3f13a77d22716b4d4bbacd3 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Wed, 3 Aug 2022 08:15:43 +0600
Subject: [PATCH 15/28] added breadcrumb demo
---
src/Wpf.Ui.Demo/App.xaml.cs | 5 ++-
.../ViewModels/BreadcrumbPagesViewModel.cs | 31 +++++++++++++++++
.../ViewModels/ButtonsViewModel.cs | 2 +-
.../ViewModels/DashboardViewModel.cs | 8 ++---
src/Wpf.Ui.Demo/Views/Container.xaml | 7 ++--
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 2 --
.../Views/Pages/BreadcrumbDemo/Page1.xaml | 25 ++++++++++++++
.../Views/Pages/BreadcrumbDemo/Page1.xaml.cs | 11 ++++++
.../Views/Pages/BreadcrumbDemo/Page2.xaml | 25 ++++++++++++++
.../Views/Pages/BreadcrumbDemo/Page2.xaml.cs | 11 ++++++
.../Views/Pages/BreadcrumbDemo/Page3.xaml | 25 ++++++++++++++
.../Views/Pages/BreadcrumbDemo/Page3.xaml.cs | 11 ++++++
src/Wpf.Ui.Demo/Views/Pages/Controls.xaml | 19 ++++++++++-
src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs | 15 ++++++--
.../Mvvm/Contracts/INavigationService.cs | 7 ++--
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 8 ++---
.../Services/Internal/NavigationManager.cs | 34 ++++++++++++-------
17 files changed, 213 insertions(+), 33 deletions(-)
create mode 100644 src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml.cs
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml.cs
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
create mode 100644 src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml.cs
diff --git a/src/Wpf.Ui.Demo/App.xaml.cs b/src/Wpf.Ui.Demo/App.xaml.cs
index a4ad04789..2af198870 100644
--- a/src/Wpf.Ui.Demo/App.xaml.cs
+++ b/src/Wpf.Ui.Demo/App.xaml.cs
@@ -93,9 +93,8 @@ public partial class App
services.AddScoped();
services.AddScoped();
-
- services.AddScoped();
- services.AddScoped();
+
+ services.AddScoped();
// Test windows
services.AddTransient();
diff --git a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
new file mode 100644
index 000000000..a71ff847c
--- /dev/null
+++ b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
@@ -0,0 +1,31 @@
+using System.Windows.Input;
+using Microsoft.Toolkit.Mvvm.Input;
+using Wpf.Ui.Mvvm.Contracts;
+
+namespace Wpf.Ui.Demo.ViewModels;
+
+public class BreadcrumbPagesViewModel
+{
+ public RelayCommand OnClickCommand { get; }
+ public ICommand OnNavigateBackCommand { get; }
+
+ private readonly INavigationService _navigationService;
+
+ public BreadcrumbPagesViewModel(INavigationService navigationService)
+ {
+ _navigationService = navigationService;
+
+ OnClickCommand = new RelayCommand(OnClick);
+ OnNavigateBackCommand = new RelayCommand(OnNavigateBack);
+ }
+
+ private void OnClick(string pageTag)
+ {
+ _navigationService.NavigateTo($"//{pageTag}", this);
+ }
+
+ private void OnNavigateBack()
+ {
+ _navigationService.NavigateTo("..");
+ }
+}
diff --git a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
index 877d7fb81..8435b08d3 100644
--- a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
@@ -30,6 +30,6 @@ public ButtonsViewModel(INavigationService navigationService)
private void OnShowMore(string parameter)
{
- _navigationService.Navigate(typeof(Views.Pages.Input));
+ _navigationService.NavigateTo("//input");
}
}
diff --git a/src/Wpf.Ui.Demo/ViewModels/DashboardViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/DashboardViewModel.cs
index 038786190..4c7c89793 100644
--- a/src/Wpf.Ui.Demo/ViewModels/DashboardViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/DashboardViewModel.cs
@@ -47,19 +47,19 @@ private void OnNavigate(string parameter)
switch (parameter)
{
case "navigate_to_input":
- _navigationService.Navigate(typeof(Views.Pages.Input));
+ _navigationService.NavigateTo(typeof(Views.Pages.Input));
return;
case "navigate_to_controls":
- _navigationService.Navigate(typeof(Views.Pages.Controls));
+ _navigationService.NavigateTo(typeof(Views.Pages.Controls));
return;
case "navigate_to_colors":
- _navigationService.Navigate(typeof(Views.Pages.Colors));
+ _navigationService.NavigateTo(typeof(Views.Pages.Colors));
return;
case "navigate_to_icons":
- _navigationService.Navigate(typeof(Views.Pages.Icons));
+ _navigationService.NavigateTo(typeof(Views.Pages.Icons));
return;
}
}
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index 7a8c2cd76..c4f93ec6a 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -2,6 +2,7 @@
x:Class="Wpf.Ui.Demo.Views.Container"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:breadcrumbDemo="clr-namespace:Wpf.Ui.Demo.Views.Pages.BreadcrumbDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:demo="clr-namespace:Wpf.Ui.Demo"
xmlns:diagnostics="clr-namespace:Wpf.Ui.Demo.Views.Diagnostics"
@@ -99,8 +100,10 @@
Icon="DarkTheme24" />
-
-
+
+
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 92430ad2a..0bb13e39c 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -135,8 +135,6 @@ private async void InvokeSplashScreen()
RootMainGrid.Visibility = Visibility.Visible;
NavigateTo(typeof(Pages.Dashboard));
- NavigateTo("//test");
- NavigateTo("//test2");
_taskBarService.SetState(this, TaskBarProgressState.None);
}
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
new file mode 100644
index 000000000..cce9435fe
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml.cs
new file mode 100644
index 000000000..2f18ed5a9
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows.Controls;
+
+namespace Wpf.Ui.Demo.Views.Pages.BreadcrumbDemo;
+
+public partial class Page1 : Page
+{
+ public Page1()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
new file mode 100644
index 000000000..36b3303e5
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml.cs
new file mode 100644
index 000000000..452815201
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows.Controls;
+
+namespace Wpf.Ui.Demo.Views.Pages.BreadcrumbDemo;
+
+public partial class Page2 : Page
+{
+ public Page2()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
new file mode 100644
index 000000000..bd897d338
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml.cs
new file mode 100644
index 000000000..5c2059e40
--- /dev/null
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml.cs
@@ -0,0 +1,11 @@
+using System.Windows.Controls;
+
+namespace Wpf.Ui.Demo.Views.Pages.BreadcrumbDemo;
+
+public partial class Page3 : Page
+{
+ public Page3()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml
index c00c43d1e..f52cba0da 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml
+++ b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml
@@ -29,6 +29,7 @@
+
@@ -84,6 +85,22 @@
Text="Opens the MessageBox." />
+
+
+
+
+
+
+
();
+ _navigation.NavigateTo("//page1", viewModel);
+ }
}
diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
index bbf3feca5..73bf29cfa 100644
--- a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
@@ -3,6 +3,7 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
+#nullable enable
using System;
using System.Windows.Controls;
using Wpf.Ui.Controls.Interfaces;
@@ -56,11 +57,13 @@ public interface INavigationService
/// Lets you navigate to the selected page based on it's tag. Should be used with .
///
/// Tag of the page.
- void Navigate(string pageTag);
+ ///
+ void NavigateTo(string pageTag, object? dataContext = null);
///
/// TODO
///
///
- void Navigate(Type type);
+ ///
+ void NavigateTo(Type type, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 83fef0202..3aa69d58f 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -81,14 +81,14 @@ public void SetPageService(IPageService pageService)
}
///
- public void Navigate(string pageTag)
+ public void NavigateTo(string pageTag, object? dataContext = null)
{
- NavigationControl.NavigateTo(pageTag);
+ NavigationControl.NavigateTo(pageTag, dataContext);
}
///
- public void Navigate(Type type)
+ public void NavigateTo(Type type, object? dataContext = null)
{
- NavigationControl.NavigateTo(type);
+ NavigationControl.NavigateTo(type, dataContext);
}
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 1f6e9ace7..150020b7c 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -120,7 +120,13 @@ private void NavigateInternal(int itemId, object? dataContext)
AddToNavigationStack(item);
- item.IsActive = true;
+ if (NavigationStack.Count > 1)
+ {
+ if (NavigationStack[NavigationStack.Count - 1].IsHidden)
+ item.IsActive = true;
+ }
+ else
+ item.IsActive = true;
if (_isBackwardsNavigated)
{
@@ -166,11 +172,8 @@ private void AddToNavigationStack(INavigationItem item)
private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
{
- if (_pageService is not null)
- {
- NavigateByService(itemData);
+ if (_pageService is not null && NavigateByService(itemData))
return;
- }
if (itemData.item.Cache)
{
@@ -178,23 +181,28 @@ private void PerformNavigation((int itemId, INavigationItem item) itemData, obje
return;
}
- NavigateWithoutCache(itemData.item, dataContext);
+ if (NavigateWithoutCache(itemData.item, dataContext) is not null)
+ return;
+
+ ThrowHelper.ThrowInvalidOperationException("failed to navigate");
}
- private void NavigateByService((int itemId, INavigationItem item) itemData)
+ private bool NavigateByService((int itemId, INavigationItem item) itemData)
{
if (itemData.item.PageType is null)
- return;
+ return false;
- if (_instances[itemData.itemId] is not null)
+ /*if (_instances[itemData.itemId] is not null)
{
//TODO
- }
+ }*/
var instance = _pageService!.GetPage(itemData.item.PageType);
- Guard.IsNotNull(instance, "Page instance");
+ if (instance is null)
+ return false;
_frame.Navigate(instance);
+ return true;
}
private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
@@ -234,12 +242,14 @@ private void NavigateWithCache((int itemId, INavigationItem item) itemData, obje
}
#if DEBUG
+ if (instance is null)
+ return instance;
+
string navigationType = item.PageType is not null ? "type" : "source";
System.Diagnostics.Debug.WriteLine(
$"DEBUG | {item.PageTag} navigated internally, without cache by it's {navigationType}.");
#endif
-
return instance;
}
From 9a2a6bb1a199f81dcde6aa4939956686a670996f Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Wed, 3 Aug 2022 10:46:14 +0600
Subject: [PATCH 16/28] fixed navigation backwards with breadcrumb elements
---
src/Wpf.Ui.Demo/Views/Container.xaml | 5 ++
.../Views/Pages/BreadcrumbDemo/Page1.xaml | 4 +-
.../Views/Pages/BreadcrumbDemo/Page2.xaml | 4 +-
.../Views/Pages/BreadcrumbDemo/Page3.xaml | 4 +-
.../Controls/Interfaces/INavigationItem.cs | 5 ++
.../Controls/Navigation/NavigationBase.cs | 2 +-
src/Wpf.Ui/Controls/NavigationItem.cs | 3 +
.../Services/Internal/NavigationManager.cs | 83 ++++++++++++++-----
8 files changed, 82 insertions(+), 28 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index c4f93ec6a..c6a971ab5 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -244,5 +244,10 @@
+
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
index cce9435fe..d3e8394ee 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page1.xaml
@@ -18,8 +18,8 @@
-
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
index 36b3303e5..583c4cc4a 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page2.xaml
@@ -18,8 +18,8 @@
-
+
diff --git a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
index bd897d338..7b4089dd7 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
+++ b/src/Wpf.Ui.Demo/Views/Pages/BreadcrumbDemo/Page3.xaml
@@ -18,8 +18,8 @@
-
+
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
index e9ab5fe1b..9ff4c1fa7 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigationItem.cs
@@ -61,4 +61,9 @@ public interface INavigationItem
/// TODO
///
internal bool IsHidden { get; set; }
+
+ ///
+ ///
+ ///
+ internal bool WasInBreadcrumb { get; set; }
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 67043b777..e409bd1ca 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -230,7 +230,7 @@ public event RoutedNavigationEvent NavigatedBackward
#endregion
///
- public bool CanGoBack => _navigationManager.CanGoBack;
+ public bool CanGoBack => !DesignerProperties.GetIsInDesignMode(this) && _navigationManager.CanGoBack;
public ObservableCollection NavigationStack => _navigationManager.NavigationStack;
diff --git a/src/Wpf.Ui/Controls/NavigationItem.cs b/src/Wpf.Ui/Controls/NavigationItem.cs
index 95ab1cbe3..427cd3781 100644
--- a/src/Wpf.Ui/Controls/NavigationItem.cs
+++ b/src/Wpf.Ui/Controls/NavigationItem.cs
@@ -240,6 +240,9 @@ protected virtual Uri BaseUri
///
bool INavigationItem.IsHidden { get; set; }
+ ///
+ bool INavigationItem.WasInBreadcrumb { get; set; }
+
///
protected override void OnContentChanged(object oldContent, object newContent)
{
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 150020b7c..05e30701e 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -20,6 +20,7 @@ internal sealed class NavigationManager : IDisposable
private readonly List _history = new();
private readonly IPageService? _pageService;
private readonly ArrayPool _arrayPool = ArrayPool.Create();
+ private readonly List _navigationStackHistory = new();
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
@@ -38,7 +39,7 @@ public NavigationManager(Frame frame, IPageService? pageService, INavigationItem
public void Dispose()
{
-
+ _navigationStackHistory.Clear();
}
public void Preload()
@@ -119,31 +120,39 @@ private void NavigateInternal(int itemId, object? dataContext)
}
AddToNavigationStack(item);
-
- if (NavigationStack.Count > 1)
- {
- if (NavigationStack[NavigationStack.Count - 1].IsHidden)
- item.IsActive = true;
- }
- else
- item.IsActive = true;
-
- if (_isBackwardsNavigated)
- {
- _isBackwardsNavigated = false;
- _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 2]));
- _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 1]));
- }
-
- _history.Add(itemId);
+ ActivateItem(item);
+ AddToHistory(itemId);
PerformNavigation((itemId, item), dataContext);
}
private void AddToNavigationStack(INavigationItem item)
{
+ if (_isBackwardsNavigated && item.WasInBreadcrumb)
+ {
+ if (_navigationStackHistory.Count > 1)
+ {
+ for (var i = 0; i < _navigationStackHistory.Count - 1; i++)
+ {
+ _addToNavigationStack = true;
+
+ var historyItem = _navigationStackHistory[i];
+ historyItem.WasInBreadcrumb = false;
+ AddToNavigationStack(historyItem);
+ }
+
+ _navigationStackHistory.Clear();
+ }
+
+ item.WasInBreadcrumb = false;
+ _addToNavigationStack = true;
+ }
+
if (_addToNavigationStack && !NavigationStack.Contains(item))
+ {
+ item.WasInBreadcrumb = true;
NavigationStack.Add(item);
+ }
if (!item.IsHidden && !_addToNavigationStack)
{
@@ -161,9 +170,34 @@ private void AddToNavigationStack(INavigationItem item)
navItem.IsActive = false;
var index = NavigationStack.IndexOf(item);
- if (index < navigationStackCount - 1)
+ if (index < navigationStackCount - 1 && _navigationStackHistory.Count == 0)
ClearNavigationStack(++index);
}
+
+ _addToNavigationStack = false;
+ }
+
+ private void ActivateItem(INavigationItem item)
+ {
+ if (NavigationStack.Count > 1)
+ {
+ if (NavigationStack[NavigationStack.Count - 1].IsHidden)
+ item.IsActive = true;
+ }
+ else
+ item.IsActive = true;
+ }
+
+ private void AddToHistory(int itemId)
+ {
+ if (_isBackwardsNavigated)
+ {
+ _isBackwardsNavigated = false;
+ _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 2]));
+ _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 1]));
+ }
+
+ _history.Add(itemId);
}
#endregion
@@ -260,7 +294,8 @@ private void NavigateWithCache((int itemId, INavigationItem item) itemData, obje
private void ClearNavigationStack(int navigationStackItemIndex)
{
var navigationStackCount = NavigationStack.Count;
- var buffer = _arrayPool.Rent(navigationStackCount - navigationStackItemIndex);
+ var length = navigationStackCount - navigationStackItemIndex;
+ var buffer = _arrayPool.Rent(length);
int i = 0;
for (int j = navigationStackItemIndex; j <= navigationStackCount - 1; j++)
@@ -269,9 +304,15 @@ private void ClearNavigationStack(int navigationStackItemIndex)
i++;
}
- foreach (var item in buffer)
+ for (var index = 0; index < length; index++)
+ {
+ var item = buffer[index];
NavigationStack.Remove(item);
+ if (length > 1)
+ _navigationStackHistory.Add(item);
+ }
+
_arrayPool.Return(buffer, true);
}
From 29df3da6b050b732fb1428796eeea4685cb675f1 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Wed, 3 Aug 2022 13:38:39 +0600
Subject: [PATCH 17/28] the stack navigation parameter has been changed
---
src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs | 2 +-
src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs | 2 +-
src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs | 2 +-
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
index a71ff847c..80037cd82 100644
--- a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
@@ -21,7 +21,7 @@ public BreadcrumbPagesViewModel(INavigationService navigationService)
private void OnClick(string pageTag)
{
- _navigationService.NavigateTo($"//{pageTag}", this);
+ _navigationService.NavigateTo($"/{pageTag}", this);
}
private void OnNavigateBack()
diff --git a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
index 8435b08d3..d792b7a92 100644
--- a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
@@ -30,6 +30,6 @@ public ButtonsViewModel(INavigationService navigationService)
private void OnShowMore(string parameter)
{
- _navigationService.NavigateTo("//input");
+ _navigationService.NavigateTo("/input");
}
}
diff --git a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
index 7a25490b1..a1a574d82 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
@@ -115,6 +115,6 @@ private void MessageBox_RightButtonClick(object sender, System.Windows.RoutedEve
private void OnBreadcrumbButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = _serviceProvider.GetRequiredService();
- _navigation.NavigateTo("//page1", viewModel);
+ _navigation.NavigateTo("/page1", viewModel);
}
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 05e30701e..0a305a7ad 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -68,9 +68,9 @@ public void NavigateTo(string tag, object? dataContext = null)
return;
}
- _addToNavigationStack = tag.Contains("//");
+ _addToNavigationStack = tag.Contains("/");
if (_addToNavigationStack)
- tag = tag.Replace("//", string.Empty).Trim();
+ tag = tag.Remove(0, 1);
var itemId = GetItemId(item => item.PageTag == tag);
if (itemId < 0)
From bfef37e5858c51b36ee454670eaaa3e59ddbee93 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Fri, 5 Aug 2022 09:07:53 +0600
Subject: [PATCH 18/28] unsubscribed from events
---
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 7 +++++++
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 2 ++
2 files changed, 9 insertions(+)
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index e409bd1ca..344aa4108 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -267,11 +267,13 @@ protected NavigationBase()
Unloaded += OnUnloaded;
}
+ ///
public void SetIPageService(IPageService pageService)
{
_pageService = pageService;
}
+ ///
public void Preload() => _navigationManager.Preload();
///
@@ -314,11 +316,16 @@ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
{
+ Loaded -= OnLoaded;
+ Unloaded -= OnUnloaded;
+
_frameManager.Dispose();
_navigationManager.Dispose();
foreach (var item in _items)
item.Click -= OnNavigationItemClicked;
+
+ _items = null!;
}
///
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 0a305a7ad..069e4e8ff 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -39,7 +39,9 @@ public NavigationManager(Frame frame, IPageService? pageService, INavigationItem
public void Dispose()
{
+ NavigationStack.Clear();
_navigationStackHistory.Clear();
+ ClearCache();
}
public void Preload()
From ac344a81d71baf14ffbdb0fb0faa80c0af71b29f Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Fri, 5 Aug 2022 14:40:50 +0600
Subject: [PATCH 19/28] fixed firing of navigated event when navigation is not
happened
---
.../Controls/Navigation/NavigationBase.cs | 8 +--
.../Services/Internal/NavigationManager.cs | 51 +++++++++++--------
2 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 344aa4108..ad5b35a99 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -282,15 +282,15 @@ public void SetIPageService(IPageService pageService)
///
public void NavigateTo(string pageTag, object? dataContext = null)
{
- _navigationManager.NavigateTo(pageTag, dataContext);
- OnNavigated();
+ if (_navigationManager.NavigateTo(pageTag, dataContext))
+ OnNavigated();
}
///
public void NavigateTo(Type type, object? dataContext = null)
{
- _navigationManager.NavigateTo(type, dataContext);
- OnNavigated();
+ if (_navigationManager.NavigateTo(type, dataContext))
+ OnNavigated();
}
///
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 069e4e8ff..0d0491fd7 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -60,14 +60,13 @@ public void ClearCache()
}
}
- public void NavigateTo(string tag, object? dataContext = null)
+ public bool NavigateTo(string tag, object? dataContext = null)
{
Guard.IsNotNullOrEmpty(tag, nameof(tag));
if (tag == "..")
{
- NavigateBack();
- return;
+ return NavigateBack();
}
_addToNavigationStack = tag.Contains("/");
@@ -78,16 +77,16 @@ public void NavigateTo(string tag, object? dataContext = null)
if (itemId < 0)
ThrowHelper.ThrowArgumentException($"Item with: {tag} tag not found");
- NavigateInternal(itemId, dataContext);
+ return NavigateInternal(itemId, dataContext);
}
- public void NavigateTo(Type type, object? dataContext = null)
+ public bool NavigateTo(Type type, object? dataContext = null)
{
var itemId = GetItemId(serviceItem => serviceItem.PageType == type);
if (itemId < 0)
ThrowHelper.ThrowArgumentException($"Item with: {type} type not found");
- NavigateInternal(itemId, dataContext);
+ return NavigateInternal(itemId, dataContext);
}
public void NavigateTo(int id, object? dataContext = null)
@@ -97,25 +96,25 @@ public void NavigateTo(int id, object? dataContext = null)
#region NavigationInternal
- private void NavigateBack()
+ private bool NavigateBack()
{
if (_history.Count <= 1)
- return;
+ return false;
var itemId = _history[_history.Count - 2];
_isBackwardsNavigated = true;
- NavigateInternal(itemId, null);
+ return NavigateInternal(itemId, null);
}
- private void NavigateInternal(int itemId, object? dataContext)
+ private bool NavigateInternal(int itemId, object? dataContext)
{
if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
- return;
+ return false;
switch (NavigationStack.Count)
{
case > 0 when NavigationStack[NavigationStack.Count -1] == item:
- return;
+ return false;
case 0:
NavigationStack.Add(item);
break;
@@ -126,6 +125,7 @@ private void NavigateInternal(int itemId, object? dataContext)
AddToHistory(itemId);
PerformNavigation((itemId, item), dataContext);
+ return true;
}
private void AddToNavigationStack(INavigationItem item)
@@ -208,8 +208,11 @@ private void AddToHistory(int itemId)
private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
{
- if (_pageService is not null && NavigateByService(itemData))
+ if (_pageService is not null)
+ {
+ NavigateByService(itemData);
return;
+ }
if (itemData.item.Cache)
{
@@ -223,10 +226,9 @@ private void PerformNavigation((int itemId, INavigationItem item) itemData, obje
ThrowHelper.ThrowInvalidOperationException("failed to navigate");
}
- private bool NavigateByService((int itemId, INavigationItem item) itemData)
+ private void NavigateByService((int itemId, INavigationItem item) itemData)
{
- if (itemData.item.PageType is null)
- return false;
+ Guard.IsNotNull(itemData.item.PageType, nameof(itemData.item.PageType));
/*if (_instances[itemData.itemId] is not null)
{
@@ -235,18 +237,25 @@ private bool NavigateByService((int itemId, INavigationItem item) itemData)
var instance = _pageService!.GetPage(itemData.item.PageType);
if (instance is null)
- return false;
+ {
+ ThrowHelper.ThrowArgumentNullException("Failed to create instance");
+ return;
+ }
_frame.Navigate(instance);
- return true;
}
private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
{
if (_instances[itemData.itemId] is null)
{
- _instances[itemData.itemId] = NavigateWithoutCache(itemData.item, dataContext);
- return;
+ if (NavigateWithoutCache(itemData.item, dataContext) is not { } element)
+ {
+ ThrowHelper.ThrowArgumentNullException("Failed to create instance");
+ return;
+ }
+
+ _instances[itemData.itemId] = element;
}
var instance = _instances[itemData.itemId]!;
@@ -256,10 +265,8 @@ private void NavigateWithCache((int itemId, INavigationItem item) itemData, obje
_frame.Navigate(instance);
-#if DEBUG
System.Diagnostics.Debug.WriteLine(
$"DEBUG | {itemData.item.PageTag} navigated internally, with cache by it's instance.");
-#endif
}
private FrameworkElement? NavigateWithoutCache(INavigationItem item, object? dataContext)
From 744960da8803911d126e51fc4a28868fe89e9c6f Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Sun, 7 Aug 2022 07:44:08 +0600
Subject: [PATCH 20/28] CommunityToolkit.Diagnostics has been updated to
version 8.0.0
---
src/Packages.props | 2 +-
src/Wpf.Ui/Controls/Breadcrumb.cs | 2 +-
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 2 +-
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 2 +-
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 15 +++++----------
src/Wpf.Ui/Wpf.Ui.csproj | 2 +-
6 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/src/Packages.props b/src/Packages.props
index d3ada50a2..0b215faf7 100644
--- a/src/Packages.props
+++ b/src/Packages.props
@@ -7,6 +7,6 @@
-
+
\ No newline at end of file
diff --git a/src/Wpf.Ui/Controls/Breadcrumb.cs b/src/Wpf.Ui/Controls/Breadcrumb.cs
index 0d4cd7fce..c4704ac5c 100644
--- a/src/Wpf.Ui/Controls/Breadcrumb.cs
+++ b/src/Wpf.Ui/Controls/Breadcrumb.cs
@@ -8,7 +8,7 @@
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
-using Microsoft.Toolkit.Diagnostics;
+using CommunityToolkit.Diagnostics;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.Interfaces;
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index ad5b35a99..d8d93008b 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -12,7 +12,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
-using Microsoft.Toolkit.Diagnostics;
+using CommunityToolkit.Diagnostics;
using Wpf.Ui.Common;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 3aa69d58f..0d973fddc 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -6,7 +6,7 @@
#nullable enable
using System;
using System.Windows.Controls;
-using Microsoft.Toolkit.Diagnostics;
+using CommunityToolkit.Diagnostics;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 0d0491fd7..de80e4f1b 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -6,7 +6,7 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
-using Microsoft.Toolkit.Diagnostics;
+using CommunityToolkit.Diagnostics;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
@@ -208,11 +208,8 @@ private void AddToHistory(int itemId)
private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
{
- if (_pageService is not null)
- {
- NavigateByService(itemData);
+ if (_pageService is not null && NavigateByService(itemData))
return;
- }
if (itemData.item.Cache)
{
@@ -226,7 +223,7 @@ private void PerformNavigation((int itemId, INavigationItem item) itemData, obje
ThrowHelper.ThrowInvalidOperationException("failed to navigate");
}
- private void NavigateByService((int itemId, INavigationItem item) itemData)
+ private bool NavigateByService((int itemId, INavigationItem item) itemData)
{
Guard.IsNotNull(itemData.item.PageType, nameof(itemData.item.PageType));
@@ -237,12 +234,10 @@ private void NavigateByService((int itemId, INavigationItem item) itemData)
var instance = _pageService!.GetPage(itemData.item.PageType);
if (instance is null)
- {
- ThrowHelper.ThrowArgumentNullException("Failed to create instance");
- return;
- }
+ return false;
_frame.Navigate(instance);
+ return true;
}
private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
diff --git a/src/Wpf.Ui/Wpf.Ui.csproj b/src/Wpf.Ui/Wpf.Ui.csproj
index 01cbf0cce..f86152436 100644
--- a/src/Wpf.Ui/Wpf.Ui.csproj
+++ b/src/Wpf.Ui/Wpf.Ui.csproj
@@ -72,7 +72,7 @@
-
+
From 9dfa6e1304cf0564e0c8bd781111ec4e7dfb0b64 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 15 Aug 2022 17:39:49 +0600
Subject: [PATCH 21/28] added INavigationCancelable
---
.../Interfaces/INavigationCancelable.cs | 13 ++
.../Services/Internal/NavigationManager.cs | 112 +++++++-----------
2 files changed, 57 insertions(+), 68 deletions(-)
create mode 100644 src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
diff --git a/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs b/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
new file mode 100644
index 000000000..f94dcde23
--- /dev/null
+++ b/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
@@ -0,0 +1,13 @@
+namespace Wpf.Ui.Common.Interfaces;
+
+///
+/// TODO
+///
+public interface INavigationCancelable
+{
+ ///
+ /// TODO
+ ///
+ ///
+ bool CouldNavigate();
+}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index de80e4f1b..acf03b72a 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -7,6 +7,7 @@
using System.Windows;
using System.Windows.Controls;
using CommunityToolkit.Diagnostics;
+using Wpf.Ui.Common.Interfaces;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;
@@ -111,6 +112,14 @@ private bool NavigateInternal(int itemId, object? dataContext)
if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
return false;
+ var instance = GetFrameworkElement((itemId, item), dataContext);
+
+ if (!CheckForNavigationCanceling(item, instance))
+ {
+ _addToNavigationStack = false;
+ return false;
+ }
+
switch (NavigationStack.Count)
{
case > 0 when NavigationStack[NavigationStack.Count -1] == item:
@@ -124,7 +133,7 @@ private bool NavigateInternal(int itemId, object? dataContext)
ActivateItem(item);
AddToHistory(itemId);
- PerformNavigation((itemId, item), dataContext);
+ _frame.Navigate(instance);
return true;
}
@@ -202,99 +211,66 @@ private void AddToHistory(int itemId)
_history.Add(itemId);
}
- #endregion
-
- #region PerformNavigation
-
- private void PerformNavigation((int itemId, INavigationItem item) itemData, object? dataContext)
+ private bool CheckForNavigationCanceling(INavigationItem item, FrameworkElement instance)
{
- if (_pageService is not null && NavigateByService(itemData))
- return;
-
- if (itemData.item.Cache)
+ INavigationCancelable? navigationCancelable = instance switch
{
- NavigateWithCache(itemData, dataContext);
- return;
- }
+ INavigationCancelable cancelable => cancelable,
+ {DataContext: INavigationCancelable dataContextNavigationCancelable} => dataContextNavigationCancelable,
+ _ => null
+ };
- if (NavigateWithoutCache(itemData.item, dataContext) is not null)
- return;
+ if (navigationCancelable is null)
+ return true;
- ThrowHelper.ThrowInvalidOperationException("failed to navigate");
+ return navigationCancelable.CouldNavigate();
}
- private bool NavigateByService((int itemId, INavigationItem item) itemData)
+ #endregion
+
+ #region PrivateMethods
+
+ private FrameworkElement GetFrameworkElement((int itemId, INavigationItem item) itemData, object? dataContext)
{
Guard.IsNotNull(itemData.item.PageType, nameof(itemData.item.PageType));
- /*if (_instances[itemData.itemId] is not null)
- {
- //TODO
- }*/
+ if (_pageService is not null && _pageService!.GetPage(itemData.item.PageType) is { } fromServicesElement)
+ return fromServicesElement;
- var instance = _pageService!.GetPage(itemData.item.PageType);
- if (instance is null)
- return false;
- _frame.Navigate(instance);
- return true;
- }
+ if (itemData.item.Cache)
+ return GetFrameworkElementFromCache(itemData, dataContext);
- private void NavigateWithCache((int itemId, INavigationItem item) itemData, object? dataContext)
- {
- if (_instances[itemData.itemId] is null)
+ if (!itemData.item.Cache && NavigationServiceActivator.CreateInstance(itemData.item.PageType, dataContext) is { } element)
{
- if (NavigateWithoutCache(itemData.item, dataContext) is not { } element)
- {
- ThrowHelper.ThrowArgumentNullException("Failed to create instance");
- return;
- }
+ if (dataContext is not null)
+ element.DataContext = dataContext;
- _instances[itemData.itemId] = element;
+ return element;
}
- var instance = _instances[itemData.itemId]!;
-
- if (dataContext is not null)
- instance.DataContext = dataContext;
-
- _frame.Navigate(instance);
-
- System.Diagnostics.Debug.WriteLine(
- $"DEBUG | {itemData.item.PageTag} navigated internally, with cache by it's instance.");
+ ThrowHelper.ThrowArgumentException("Failed to create instance");
+ return null;
}
- private FrameworkElement? NavigateWithoutCache(INavigationItem item, object? dataContext)
+ private FrameworkElement GetFrameworkElementFromCache((int itemId, INavigationItem item) itemData, object? dataContext)
{
- FrameworkElement? instance = null;
+ if (_instances[itemData.itemId] is not null)
+ return _instances[itemData.itemId]!;
- if (item.PageType is not null)
+ if (NavigationServiceActivator.CreateInstance(itemData.item.PageType, dataContext) is not { } element)
{
- instance = NavigationServiceActivator.CreateInstance(item.PageType, dataContext);
- _frame.Navigate(instance);
+ ThrowHelper.ThrowArgumentNullException("Failed to create instance");
+ return null;
}
- if (item.AbsolutePageSource is not null)
- {
- _frame.Navigate(item.AbsolutePageSource);
- }
-
-#if DEBUG
- if (instance is null)
- return instance;
-
- string navigationType = item.PageType is not null ? "type" : "source";
+ if (dataContext is not null)
+ element.DataContext = dataContext;
- System.Diagnostics.Debug.WriteLine(
- $"DEBUG | {item.PageTag} navigated internally, without cache by it's {navigationType}.");
-#endif
- return instance;
+ _instances[itemData.itemId] = element;
+ return _instances[itemData.itemId]!;
}
- #endregion
-
- #region PrivateMethods
-
private void ClearNavigationStack(int navigationStackItemIndex)
{
var navigationStackCount = NavigationStack.Count;
From 921e6bd5e2ecd4a98508edd86e258dd25a901f09 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 15 Aug 2022 21:32:58 +0600
Subject: [PATCH 22/28] added parameters for RoutedNavigationEventArgs
---
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 7 ++---
.../Interfaces/INavigationCancelable.cs | 7 +++--
.../Common/RoutedNavigationEventArgs.cs | 22 ++++++++------
.../Controls/Navigation/NavigationBase.cs | 30 +------------------
.../Services/Internal/NavigationManager.cs | 21 ++++++++-----
5 files changed, 34 insertions(+), 53 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index 0bb13e39c..aa02a4864 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -154,18 +154,15 @@ private void TrayMenuItem_OnClick(object sender, RoutedEventArgs e)
private void RootNavigation_OnNavigated(INavigation sender, RoutedNavigationEventArgs e)
{
- var current = sender.NavigationStack[sender.NavigationStack.Count - 1];
-
- System.Diagnostics.Debug.WriteLine($"DEBUG | WPF UI Navigated to: {current}", "Wpf.Ui.Demo");
+ System.Diagnostics.Debug.WriteLine($"DEBUG | WPF UI Navigated to: {e.NavigatedTo}", "Wpf.Ui.Demo");
// This funky solution allows us to impose a negative
// margin for Frame only for the Dashboard page, thanks
// to which the banner will cover the entire page nicely.
RootFrame.Margin = new Thickness(
left: 0,
- top: current.PageTag == "dashboard" ? -69 : 0,
+ top: e.NavigatedTo.PageTag == "dashboard" ? -69 : 0,
right: 0,
bottom: 0);
}
}
-
diff --git a/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs b/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
index f94dcde23..baba28d42 100644
--- a/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
+++ b/src/Wpf.Ui/Common/Interfaces/INavigationCancelable.cs
@@ -1,4 +1,7 @@
-namespace Wpf.Ui.Common.Interfaces;
+#nullable enable
+using Wpf.Ui.Controls.Interfaces;
+
+namespace Wpf.Ui.Common.Interfaces;
///
/// TODO
@@ -9,5 +12,5 @@ public interface INavigationCancelable
/// TODO
///
///
- bool CouldNavigate();
+ bool CouldNavigate(INavigationItem? navigationFrom);
}
diff --git a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs b/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
index 5c5988588..d93551187 100644
--- a/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
+++ b/src/Wpf.Ui/Common/RoutedNavigationEventArgs.cs
@@ -3,26 +3,30 @@
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.
-using System.Collections.Generic;
+#nullable enable
using System.Windows;
using Wpf.Ui.Controls.Interfaces;
namespace Wpf.Ui.Common;
///
-/// with additional .
+///
///
public class RoutedNavigationEventArgs : RoutedEventArgs
{
+ public readonly INavigationItem? NavigatedFrom;
+ public readonly INavigationItem NavigatedTo;
+
///
- /// Constructor for .
+ /// TODO
///
- /// 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) : base(
- routedEvent, source)
+ ///
+ ///
+ ///
+ ///
+ public RoutedNavigationEventArgs(RoutedEvent routedEvent, INavigation source, INavigationItem? navigatedFrom, INavigationItem navigatedTo) : base(routedEvent, source)
{
-
+ NavigatedFrom = navigatedFrom;
+ NavigatedTo = navigatedTo;
}
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index d8d93008b..9a0438158 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -199,34 +199,6 @@ public event RoutedNavigationEvent Navigated
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
///
@@ -378,7 +350,7 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
protected virtual void OnNavigated()
{
- var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this);
+ var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, _navigationManager.NavigationFrom, NavigationStack[NavigationStack.Count - 1]);
RaiseEvent(newEvent);
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index acf03b72a..61990c786 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -18,7 +18,6 @@ internal sealed class NavigationManager : IDisposable
private readonly Frame _frame;
private readonly INavigationItem[] _navigationItems;
private readonly FrameworkElement?[] _instances;
- private readonly List _history = new();
private readonly IPageService? _pageService;
private readonly ArrayPool _arrayPool = ArrayPool.Create();
private readonly List _navigationStackHistory = new();
@@ -26,7 +25,9 @@ internal sealed class NavigationManager : IDisposable
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
- public bool CanGoBack => _history.Count > 1;
+ public bool CanGoBack => History.Count > 1;
+ public INavigationItem? NavigationFrom => History.Count > 1 ? _navigationItems[History[History.Count - 2]] : null;
+ public readonly List History = new();
public readonly ObservableCollection NavigationStack = new();
public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
@@ -38,6 +39,8 @@ public NavigationManager(Frame frame, IPageService? pageService, INavigationItem
_pageService = pageService;
}
+ #region Public methods
+
public void Dispose()
{
NavigationStack.Clear();
@@ -95,14 +98,16 @@ public void NavigateTo(int id, object? dataContext = null)
NavigateInternal(id, dataContext);
}
+ #endregion
+
#region NavigationInternal
private bool NavigateBack()
{
- if (_history.Count <= 1)
+ if (History.Count <= 1)
return false;
- var itemId = _history[_history.Count - 2];
+ var itemId = History[History.Count - 2];
_isBackwardsNavigated = true;
return NavigateInternal(itemId, null);
}
@@ -204,11 +209,11 @@ private void AddToHistory(int itemId)
if (_isBackwardsNavigated)
{
_isBackwardsNavigated = false;
- _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 2]));
- _history.RemoveAt(_history.LastIndexOf(_history[_history.Count - 1]));
+ History.RemoveAt(History.LastIndexOf(History[History.Count - 2]));
+ History.RemoveAt(History.LastIndexOf(History[History.Count - 1]));
}
- _history.Add(itemId);
+ History.Add(itemId);
}
private bool CheckForNavigationCanceling(INavigationItem item, FrameworkElement instance)
@@ -223,7 +228,7 @@ private bool CheckForNavigationCanceling(INavigationItem item, FrameworkElement
if (navigationCancelable is null)
return true;
- return navigationCancelable.CouldNavigate();
+ return navigationCancelable.CouldNavigate(NavigationFrom);
}
#endregion
From 49981eae1ed152d00b7e1179c0155672631a6586 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 15 Aug 2022 22:02:14 +0600
Subject: [PATCH 23/28] fixed my mistake
---
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 4 +++-
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 8 ++++----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 9a0438158..db872878e 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -350,7 +350,9 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
protected virtual void OnNavigated()
{
- var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, _navigationManager.NavigationFrom, NavigationStack[NavigationStack.Count - 1]);
+ var navigatedFrom = _navigationManager.History.Count > 1 ? _items[_navigationManager.History.Count - 2] : null;
+
+ var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, navigatedFrom, NavigationStack[NavigationStack.Count - 1]);
RaiseEvent(newEvent);
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 61990c786..571cb49af 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -26,7 +26,6 @@ internal sealed class NavigationManager : IDisposable
private bool _addToNavigationStack;
public bool CanGoBack => History.Count > 1;
- public INavigationItem? NavigationFrom => History.Count > 1 ? _navigationItems[History[History.Count - 2]] : null;
public readonly List History = new();
public readonly ObservableCollection NavigationStack = new();
@@ -119,7 +118,7 @@ private bool NavigateInternal(int itemId, object? dataContext)
var instance = GetFrameworkElement((itemId, item), dataContext);
- if (!CheckForNavigationCanceling(item, instance))
+ if (!CheckForNavigationCanceling(instance))
{
_addToNavigationStack = false;
return false;
@@ -216,7 +215,7 @@ private void AddToHistory(int itemId)
History.Add(itemId);
}
- private bool CheckForNavigationCanceling(INavigationItem item, FrameworkElement instance)
+ private bool CheckForNavigationCanceling(FrameworkElement instance)
{
INavigationCancelable? navigationCancelable = instance switch
{
@@ -228,7 +227,8 @@ private bool CheckForNavigationCanceling(INavigationItem item, FrameworkElement
if (navigationCancelable is null)
return true;
- return navigationCancelable.CouldNavigate(NavigationFrom);
+ var navigationFrom = History.Count > 0 ? _navigationItems[History[History.Count - 1]] : null;
+ return navigationCancelable.CouldNavigate(navigationFrom);
}
#endregion
From 5d5e50af57542aa066d60782f7ba24c4ce91a912 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 15 Aug 2022 22:19:46 +0600
Subject: [PATCH 24/28] added addToHistory parameter
---
src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs | 2 +-
src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs | 3 +--
src/Wpf.Ui.Demo/Views/Container.xaml | 4 ++--
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 4 ++--
src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs | 2 +-
.../Views/Windows/ExperimentalWindow.xaml.cs | 4 ++--
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 6 ++++--
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 8 ++++----
src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs | 6 ++++--
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 8 ++++----
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 10 +++++++---
11 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
index 80037cd82..28a139f78 100644
--- a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
@@ -21,7 +21,7 @@ public BreadcrumbPagesViewModel(INavigationService navigationService)
private void OnClick(string pageTag)
{
- _navigationService.NavigateTo($"/{pageTag}", this);
+ _navigationService.NavigateTo($"/{pageTag}", true, this);
}
private void OnNavigateBack()
diff --git a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
index d792b7a92..a8cb1bd5d 100644
--- a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
@@ -27,9 +27,8 @@ public ButtonsViewModel(INavigationService navigationService)
var currentTheme = testGetThemeService.GetSystemTheme();
}
-
private void OnShowMore(string parameter)
{
- _navigationService.NavigateTo("/input");
+ _navigationService.NavigateTo("/input", false);
}
}
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index c6a971ab5..8125e9bca 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -245,9 +245,9 @@
-
+ Navigation="{Binding ElementName=RootNavigation, Mode=OneTime}" />
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index aa02a4864..b520f7ee3 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -98,10 +98,10 @@ public INavigation GetNavigation()
=> RootNavigation;
public void NavigateTo(Type type, object dataContext = null)
- => RootNavigation.NavigateTo(type, dataContext);
+ => RootNavigation.NavigateTo(type, true, dataContext);
public void NavigateTo(string pageTag, object dataContext = null)
- => RootNavigation.NavigateTo(pageTag, dataContext);
+ => RootNavigation.NavigateTo(pageTag, true, dataContext);
public void SetPageService(IPageService pageService)
=> RootNavigation.SetIPageService(pageService);
diff --git a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
index a1a574d82..f13cc8e15 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
@@ -115,6 +115,6 @@ private void MessageBox_RightButtonClick(object sender, System.Windows.RoutedEve
private void OnBreadcrumbButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = _serviceProvider.GetRequiredService();
- _navigation.NavigateTo("/page1", viewModel);
+ _navigation.NavigateTo("/page1", true, viewModel);
}
}
diff --git a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
index a90b5fb71..d4d4b1dcc 100644
--- a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
@@ -140,8 +140,8 @@ public void CloseWindow()
=> Close();
public void NavigateTo(Type type, object dataContext = null)
- => RootNavigation.NavigateTo(type, dataContext);
+ => RootNavigation.NavigateTo(type, true, dataContext);
public void NavigateTo(string pageTag, object dataContext = null)
- => RootNavigation.NavigateTo(pageTag, dataContext);
+ => RootNavigation.NavigateTo(pageTag, true, dataContext);
}
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index 1eeb093aa..fa4bbe74a 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -105,13 +105,15 @@ public interface INavigation
/// TODO
///
///
+ ///
///
- void NavigateTo(string pageTag, object? dataContext = null);
+ void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null);
///
/// TODO
///
///
+ ///
///
- void NavigateTo(Type type, object? dataContext = null);
+ void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index db872878e..bb9621a3c 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -252,16 +252,16 @@ public void SetIPageService(IPageService pageService)
public void ClearCache() => _navigationManager.ClearCache();
///
- public void NavigateTo(string pageTag, object? dataContext = null)
+ public void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null)
{
- if (_navigationManager.NavigateTo(pageTag, dataContext))
+ if (_navigationManager.NavigateTo(pageTag, addToHistory, dataContext))
OnNavigated();
}
///
- public void NavigateTo(Type type, object? dataContext = null)
+ public void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null)
{
- if (_navigationManager.NavigateTo(type, dataContext))
+ if (_navigationManager.NavigateTo(type, addToHistory, dataContext))
OnNavigated();
}
diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
index 73bf29cfa..23519cd3e 100644
--- a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
@@ -57,13 +57,15 @@ public interface INavigationService
/// Lets you navigate to the selected page based on it's tag. Should be used with .
///
/// Tag of the page.
+ ///
///
- void NavigateTo(string pageTag, object? dataContext = null);
+ void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null);
///
/// TODO
///
///
+ ///
///
- void NavigateTo(Type type, object? dataContext = null);
+ void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 0d973fddc..83e07a2bd 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -81,14 +81,14 @@ public void SetPageService(IPageService pageService)
}
///
- public void NavigateTo(string pageTag, object? dataContext = null)
+ public void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null)
{
- NavigationControl.NavigateTo(pageTag, dataContext);
+ NavigationControl.NavigateTo(pageTag, addToHistory, dataContext);
}
///
- public void NavigateTo(Type type, object? dataContext = null)
+ public void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null)
{
- NavigationControl.NavigateTo(type, dataContext);
+ NavigationControl.NavigateTo(type, addToHistory, dataContext);
}
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 571cb49af..aa77b859d 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -24,6 +24,7 @@ internal sealed class NavigationManager : IDisposable
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
+ private bool _addToHistory = true;
public bool CanGoBack => History.Count > 1;
public readonly List History = new();
@@ -63,7 +64,7 @@ public void ClearCache()
}
}
- public bool NavigateTo(string tag, object? dataContext = null)
+ public bool NavigateTo(string tag, bool addToHistory, object? dataContext = null)
{
Guard.IsNotNullOrEmpty(tag, nameof(tag));
@@ -83,7 +84,7 @@ public bool NavigateTo(string tag, object? dataContext = null)
return NavigateInternal(itemId, dataContext);
}
- public bool NavigateTo(Type type, object? dataContext = null)
+ public bool NavigateTo(Type type, bool addToHistory, object? dataContext = null)
{
var itemId = GetItemId(serviceItem => serviceItem.PageType == type);
if (itemId < 0)
@@ -212,7 +213,10 @@ private void AddToHistory(int itemId)
History.RemoveAt(History.LastIndexOf(History[History.Count - 1]));
}
- History.Add(itemId);
+ if (_addToHistory)
+ History.Add(itemId);
+
+ _addToHistory = true;
}
private bool CheckForNavigationCanceling(FrameworkElement instance)
From a85a2480d83af27eba12723f3f8dd64fa875929b Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Mon, 15 Aug 2022 23:39:51 +0600
Subject: [PATCH 25/28] separated the logic of the navigation stack from the
NavigationManager
---
.../ViewModels/ButtonsViewModel.cs | 2 +-
.../Controls/Navigation/NavigationBase.cs | 2 +-
.../Services/Internal/NavigationManager.cs | 99 ++-------------
.../Internal/NavigationStackManager.cs | 119 ++++++++++++++++++
4 files changed, 129 insertions(+), 93 deletions(-)
create mode 100644 src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
diff --git a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
index a8cb1bd5d..f12bf72c1 100644
--- a/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/ButtonsViewModel.cs
@@ -29,6 +29,6 @@ public ButtonsViewModel(INavigationService navigationService)
private void OnShowMore(string parameter)
{
- _navigationService.NavigateTo("/input", false);
+ _navigationService.NavigateTo("/input");
}
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index bb9621a3c..8674845d9 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -350,7 +350,7 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
protected virtual void OnNavigated()
{
- var navigatedFrom = _navigationManager.History.Count > 1 ? _items[_navigationManager.History.Count - 2] : null;
+ var navigatedFrom = _navigationManager.History.Count > 1 ? _items[_navigationManager.History[_navigationManager.History.Count - 2]] : null;
var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, navigatedFrom, NavigationStack[NavigationStack.Count - 1]);
RaiseEvent(newEvent);
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index aa77b859d..75ad1214f 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -1,6 +1,5 @@
#nullable enable
using System;
-using System.Buffers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@@ -15,12 +14,11 @@ namespace Wpf.Ui.Services.Internal;
internal sealed class NavigationManager : IDisposable
{
+ private readonly NavigationStackManager _navigationStackManager;
private readonly Frame _frame;
private readonly INavigationItem[] _navigationItems;
private readonly FrameworkElement?[] _instances;
private readonly IPageService? _pageService;
- private readonly ArrayPool _arrayPool = ArrayPool.Create();
- private readonly List _navigationStackHistory = new();
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
@@ -28,10 +26,11 @@ internal sealed class NavigationManager : IDisposable
public bool CanGoBack => History.Count > 1;
public readonly List History = new();
- public readonly ObservableCollection NavigationStack = new();
+ public ObservableCollection NavigationStack => _navigationStackManager.NavigationStack;
public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
{
+ _navigationStackManager = new NavigationStackManager();
_instances = new FrameworkElement[navigationItems.Length];
_navigationItems = navigationItems;
@@ -43,8 +42,7 @@ public NavigationManager(Frame frame, IPageService? pageService, INavigationItem
public void Dispose()
{
- NavigationStack.Clear();
- _navigationStackHistory.Clear();
+ _navigationStackManager.Dispose();
ClearCache();
}
@@ -125,72 +123,16 @@ private bool NavigateInternal(int itemId, object? dataContext)
return false;
}
- switch (NavigationStack.Count)
- {
- case > 0 when NavigationStack[NavigationStack.Count -1] == item:
- return false;
- case 0:
- NavigationStack.Add(item);
- break;
- }
+ if (!_navigationStackManager.AddFirstItemAndCheckIfNavigatingToCurrentItem(item))
+ return false;
- AddToNavigationStack(item);
+ _navigationStackManager.AddToNavigationStack(item, _addToNavigationStack, _isBackwardsNavigated);
ActivateItem(item);
AddToHistory(itemId);
_frame.Navigate(instance);
- return true;
- }
-
- private void AddToNavigationStack(INavigationItem item)
- {
- if (_isBackwardsNavigated && item.WasInBreadcrumb)
- {
- if (_navigationStackHistory.Count > 1)
- {
- for (var i = 0; i < _navigationStackHistory.Count - 1; i++)
- {
- _addToNavigationStack = true;
-
- var historyItem = _navigationStackHistory[i];
- historyItem.WasInBreadcrumb = false;
- AddToNavigationStack(historyItem);
- }
-
- _navigationStackHistory.Clear();
- }
-
- item.WasInBreadcrumb = false;
- _addToNavigationStack = true;
- }
-
- if (_addToNavigationStack && !NavigationStack.Contains(item))
- {
- item.WasInBreadcrumb = true;
- NavigationStack.Add(item);
- }
-
- if (!item.IsHidden && !_addToNavigationStack)
- {
- NavigationStack[0].IsActive = false;
- NavigationStack[0] = item;
-
- ClearNavigationStack(1);
- }
-
- var navigationStackCount = NavigationStack.Count;
- if (navigationStackCount > 1)
- {
- var navItem = NavigationStack[NavigationStack.Count - 2];
- if (navItem.IsHidden)
- navItem.IsActive = false;
-
- var index = NavigationStack.IndexOf(item);
- if (index < navigationStackCount - 1 && _navigationStackHistory.Count == 0)
- ClearNavigationStack(++index);
- }
-
_addToNavigationStack = false;
+ return true;
}
private void ActivateItem(INavigationItem item)
@@ -280,31 +222,6 @@ private FrameworkElement GetFrameworkElementFromCache((int itemId, INavigationIt
return _instances[itemData.itemId]!;
}
- private void ClearNavigationStack(int navigationStackItemIndex)
- {
- var navigationStackCount = NavigationStack.Count;
- var length = navigationStackCount - navigationStackItemIndex;
- var buffer = _arrayPool.Rent(length);
-
- int i = 0;
- for (int j = navigationStackItemIndex; j <= navigationStackCount - 1; j++)
- {
- buffer[i] = NavigationStack[j];
- i++;
- }
-
- for (var index = 0; index < length; index++)
- {
- var item = buffer[index];
- NavigationStack.Remove(item);
-
- if (length > 1)
- _navigationStackHistory.Add(item);
- }
-
- _arrayPool.Return(buffer, true);
- }
-
private int GetItemId(Func prediction)
{
int selectedIndex = -1;
diff --git a/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
new file mode 100644
index 000000000..118ca5cfc
--- /dev/null
+++ b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using Wpf.Ui.Controls.Interfaces;
+
+namespace Wpf.Ui.Services.Internal;
+
+internal sealed class NavigationStackManager : IDisposable
+{
+ private readonly ArrayPool _arrayPool = ArrayPool.Create();
+ private readonly List _navigationStackHistory = new();
+
+ public readonly ObservableCollection NavigationStack = new();
+
+ public void Dispose()
+ {
+ NavigationStack.Clear();
+ _navigationStackHistory.Clear();
+ }
+
+ public bool AddFirstItemAndCheckIfNavigatingToCurrentItem(INavigationItem item)
+ {
+ switch (NavigationStack.Count)
+ {
+ case > 0 when NavigationStack[NavigationStack.Count -1] == item:
+ return false;
+ case 0:
+ NavigationStack.Add(item);
+ return true;
+ }
+
+ return true;
+ }
+
+ public void AddToNavigationStack(INavigationItem item, bool addToNavigationStack, bool isBackwardsNavigated)
+ {
+ if (isBackwardsNavigated)
+ RecreateBreadcrumbsFromHistory(item);
+
+ if (addToNavigationStack && !NavigationStack.Contains(item))
+ {
+ item.WasInBreadcrumb = true;
+ NavigationStack.Add(item);
+ }
+
+ if (!addToNavigationStack)
+ UpdateCurrentItem(item);
+
+ ClearNavigationStack(item);
+ }
+
+ private void UpdateCurrentItem(INavigationItem item)
+ {
+ if (item.IsHidden)
+ return;
+
+ NavigationStack[0].IsActive = false;
+ NavigationStack[0] = item;
+
+ ClearNavigationStack(1);
+ }
+
+ private void RecreateBreadcrumbsFromHistory(INavigationItem item)
+ {
+ if (!item.WasInBreadcrumb && _navigationStackHistory.Count < 1)
+ return;
+
+ for (var i = 0; i < _navigationStackHistory.Count - 1; i++)
+ {
+ var historyItem = _navigationStackHistory[i];
+ AddToNavigationStack(historyItem, true, false);
+ historyItem.WasInBreadcrumb = false;
+ }
+
+ _navigationStackHistory.Clear();
+ AddToNavigationStack(item, true, false);
+ }
+
+ private void ClearNavigationStack(INavigationItem item)
+ {
+ var navigationStackCount = NavigationStack.Count;
+ if (navigationStackCount <= 1)
+ return;
+
+ var navItem = NavigationStack[NavigationStack.Count - 2];
+ if (navItem.IsHidden)
+ navItem.IsActive = false;
+
+ var index = NavigationStack.IndexOf(item);
+ if (index < navigationStackCount - 1 && _navigationStackHistory.Count == 0)
+ ClearNavigationStack(++index);
+ }
+
+ private void ClearNavigationStack(int navigationStackItemIndex)
+ {
+ var navigationStackCount = NavigationStack.Count;
+ var length = navigationStackCount - navigationStackItemIndex;
+ var buffer = _arrayPool.Rent(length);
+
+ int i = 0;
+ for (int j = navigationStackItemIndex; j <= navigationStackCount - 1; j++)
+ {
+ buffer[i] = NavigationStack[j];
+ i++;
+ }
+
+ for (var index = 0; index < length; index++)
+ {
+ var item = buffer[index];
+ NavigationStack.Remove(item);
+
+ if (length > 1)
+ _navigationStackHistory.Add(item);
+ }
+
+ _arrayPool.Return(buffer, true);
+ }
+}
From 9f5131d3e117de3abe3ac76f34b102fb62ace73c Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 16 Aug 2022 01:02:43 +0600
Subject: [PATCH 26/28] implemented "complex history" in the
NavigationStackManager
---
src/Wpf.Ui.Demo/Views/Container.xaml | 4 +-
.../Controls/Navigation/NavigationBase.cs | 15 ++---
.../Services/Internal/NavigationManager.cs | 41 ++++++------
.../Internal/NavigationStackManager.cs | 67 +++++++++++++++----
4 files changed, 82 insertions(+), 45 deletions(-)
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml b/src/Wpf.Ui.Demo/Views/Container.xaml
index 8125e9bca..c6a971ab5 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml
@@ -245,9 +245,9 @@
-
+ Navigation="{Binding ElementName=RootNavigation, Mode=OneTime}" />-->
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 8674845d9..7200dfd21 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -28,7 +28,6 @@ public abstract class NavigationBase : System.Windows.Controls.Control, INavigat
private FrameManager _frameManager = null!;
private NavigationManager _navigationManager = null!;
private IPageService? _pageService;
- private INavigationItem[] _items = null!;
private bool _loaded;
#region DependencyProperties
@@ -272,10 +271,8 @@ protected virtual void OnLoaded(object sender, RoutedEventArgs e)
{
Guard.IsNotNull(Frame, nameof(Frame));
- _items = MergeItems();
-
_frameManager = new FrameManager(Frame, TransitionDuration, TransitionType);
- _navigationManager = new NavigationManager(Frame, _pageService, _items);
+ _navigationManager = new NavigationManager(Frame, _pageService, MergeItems());
if (SelectedPageIndex > -1)
{
@@ -291,13 +288,11 @@ protected virtual void OnUnloaded(object sender, RoutedEventArgs e)
Loaded -= OnLoaded;
Unloaded -= OnUnloaded;
- _frameManager.Dispose();
- _navigationManager.Dispose();
-
- foreach (var item in _items)
+ foreach (var item in _navigationManager.NavigationItems)
item.Click -= OnNavigationItemClicked;
- _items = null!;
+ _frameManager.Dispose();
+ _navigationManager.Dispose();
}
///
@@ -350,7 +345,7 @@ static void MoveFocus(FrameworkElement element, FocusNavigationDirection directi
///
protected virtual void OnNavigated()
{
- var navigatedFrom = _navigationManager.History.Count > 1 ? _items[_navigationManager.History[_navigationManager.History.Count - 2]] : null;
+ var navigatedFrom = _navigationManager.History.Count > 1 ? _navigationManager.NavigationItems[_navigationManager.History[_navigationManager.History.Count - 2]] : null;
var newEvent = new RoutedNavigationEventArgs(NavigatedEvent, this, navigatedFrom, NavigationStack[NavigationStack.Count - 1]);
RaiseEvent(newEvent);
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 75ad1214f..7ef437760 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -16,7 +16,6 @@ internal sealed class NavigationManager : IDisposable
{
private readonly NavigationStackManager _navigationStackManager;
private readonly Frame _frame;
- private readonly INavigationItem[] _navigationItems;
private readonly FrameworkElement?[] _instances;
private readonly IPageService? _pageService;
@@ -27,15 +26,17 @@ internal sealed class NavigationManager : IDisposable
public bool CanGoBack => History.Count > 1;
public readonly List History = new();
public ObservableCollection NavigationStack => _navigationStackManager.NavigationStack;
+ public readonly INavigationItem[] NavigationItems;
public NavigationManager(Frame frame, IPageService? pageService, INavigationItem[] navigationItems)
{
- _navigationStackManager = new NavigationStackManager();
_instances = new FrameworkElement[navigationItems.Length];
- _navigationItems = navigationItems;
+ NavigationItems = navigationItems;
_frame = frame;
_pageService = pageService;
+
+ _navigationStackManager = new NavigationStackManager(this);
}
#region Public methods
@@ -96,6 +97,21 @@ public void NavigateTo(int id, object? dataContext = null)
NavigateInternal(id, dataContext);
}
+ public int GetItemId(Func prediction)
+ {
+ int selectedIndex = -1;
+
+ for (int i = 0; i < NavigationItems.Length; i++)
+ {
+ if (!prediction.Invoke(NavigationItems[i])) continue;
+
+ selectedIndex = i;
+ break;
+ }
+
+ return selectedIndex;
+ }
+
#endregion
#region NavigationInternal
@@ -112,7 +128,7 @@ private bool NavigateBack()
private bool NavigateInternal(int itemId, object? dataContext)
{
- if (_navigationItems.ElementAtOrDefault(itemId) is not { } item)
+ if (NavigationItems.ElementAtOrDefault(itemId) is not { } item)
return false;
var instance = GetFrameworkElement((itemId, item), dataContext);
@@ -173,7 +189,7 @@ private bool CheckForNavigationCanceling(FrameworkElement instance)
if (navigationCancelable is null)
return true;
- var navigationFrom = History.Count > 0 ? _navigationItems[History[History.Count - 1]] : null;
+ var navigationFrom = History.Count > 0 ? NavigationItems[History[History.Count - 1]] : null;
return navigationCancelable.CouldNavigate(navigationFrom);
}
@@ -222,20 +238,5 @@ private FrameworkElement GetFrameworkElementFromCache((int itemId, INavigationIt
return _instances[itemData.itemId]!;
}
- private int GetItemId(Func prediction)
- {
- int selectedIndex = -1;
-
- for (int i = 0; i < _navigationItems.Length; i++)
- {
- if (!prediction.Invoke(_navigationItems[i])) continue;
-
- selectedIndex = i;
- break;
- }
-
- return selectedIndex;
- }
-
#endregion
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
index 118ca5cfc..b906001e6 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
@@ -8,15 +8,20 @@ namespace Wpf.Ui.Services.Internal;
internal sealed class NavigationStackManager : IDisposable
{
+ private readonly NavigationManager _navigationManager;
private readonly ArrayPool _arrayPool = ArrayPool.Create();
- private readonly List _navigationStackHistory = new();
-
+ private readonly Dictionary _complexHistory = new();
public readonly ObservableCollection NavigationStack = new();
+ public NavigationStackManager(NavigationManager navigationManager)
+ {
+ _navigationManager = navigationManager;
+ }
+
public void Dispose()
{
NavigationStack.Clear();
- _navigationStackHistory.Clear();
+ _complexHistory.Clear();
}
public bool AddFirstItemAndCheckIfNavigatingToCurrentItem(INavigationItem item)
@@ -52,9 +57,12 @@ public void AddToNavigationStack(INavigationItem item, bool addToNavigationStack
private void UpdateCurrentItem(INavigationItem item)
{
- if (item.IsHidden)
+ if (item.IsHidden || NavigationStack.Contains(item))
return;
+ if (NavigationStack.Count > 1)
+ AddToHistory(item);
+
NavigationStack[0].IsActive = false;
NavigationStack[0] = item;
@@ -63,17 +71,29 @@ private void UpdateCurrentItem(INavigationItem item)
private void RecreateBreadcrumbsFromHistory(INavigationItem item)
{
- if (!item.WasInBreadcrumb && _navigationStackHistory.Count < 1)
+ if (!item.WasInBreadcrumb && !_complexHistory.ContainsKey(item))
return;
- for (var i = 0; i < _navigationStackHistory.Count - 1; i++)
+ var history = _complexHistory[item];
+
+ var startIndex = 0;
+
+ var index = _navigationManager.GetItemId(navigationItem => navigationItem == history[0]);
+ if (index > 0 && !history[0].IsHidden)
+ {
+ startIndex = 1;
+ NavigationStack[0].IsActive = false;
+ NavigationStack[0] = history[0];
+ }
+
+ for (var i = startIndex; i < history.Length; i++)
{
- var historyItem = _navigationStackHistory[i];
+ var historyItem = history[i];
AddToNavigationStack(historyItem, true, false);
historyItem.WasInBreadcrumb = false;
}
- _navigationStackHistory.Clear();
+ _complexHistory.Remove(item);
AddToNavigationStack(item, true, false);
}
@@ -88,8 +108,12 @@ private void ClearNavigationStack(INavigationItem item)
navItem.IsActive = false;
var index = NavigationStack.IndexOf(item);
- if (index < navigationStackCount - 1 && _navigationStackHistory.Count == 0)
- ClearNavigationStack(++index);
+ if (index >= navigationStackCount - 1 || _complexHistory.ContainsKey(item))
+ return;
+
+ AddToHistory(item);
+
+ ClearNavigationStack(++index);
}
private void ClearNavigationStack(int navigationStackItemIndex)
@@ -109,11 +133,28 @@ private void ClearNavigationStack(int navigationStackItemIndex)
{
var item = buffer[index];
NavigationStack.Remove(item);
-
- if (length > 1)
- _navigationStackHistory.Add(item);
}
_arrayPool.Return(buffer, true);
}
+
+ private void AddToHistory(INavigationItem item)
+ {
+ var lastItem = NavigationStack[NavigationStack.Count - 1];
+ var startIndex = NavigationStack.IndexOf(item);
+ if (startIndex < 0)
+ startIndex = 0;
+
+ if (_complexHistory.ContainsKey(lastItem))
+ _complexHistory.Remove(lastItem);
+
+ _complexHistory.Add(lastItem, new INavigationItem[NavigationStack.Count - 1 - startIndex]);
+
+ int i = 0;
+ for (int j = startIndex; j < NavigationStack.Count - 1; j++)
+ {
+ _complexHistory[lastItem][i] = NavigationStack[j];
+ i++;
+ }
+ }
}
From 552763406528dad2955c75e2c44252e1469d5dff Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 16 Aug 2022 08:22:30 +0600
Subject: [PATCH 27/28] fixed my mistake
---
src/Wpf.Ui/Services/Internal/NavigationStackManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
index b906001e6..a2f59c6f2 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationStackManager.cs
@@ -79,7 +79,7 @@ private void RecreateBreadcrumbsFromHistory(INavigationItem item)
var startIndex = 0;
var index = _navigationManager.GetItemId(navigationItem => navigationItem == history[0]);
- if (index > 0 && !history[0].IsHidden)
+ if (index >= 0 && !history[0].IsHidden)
{
startIndex = 1;
NavigationStack[0].IsActive = false;
From 6f116cb8957c1352c5b30d8f5159af71f06d64f2 Mon Sep 17 00:00:00 2001
From: Ivan Dmitriev <42055372+IvanDmitriev1@users.noreply.github.com>
Date: Tue, 16 Aug 2022 09:00:04 +0600
Subject: [PATCH 28/28] removed addToHistory parameter
---
src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs | 2 +-
src/Wpf.Ui.Demo/Views/Container.xaml.cs | 4 ++--
src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs | 2 +-
.../Views/Windows/ExperimentalWindow.xaml.cs | 4 ++--
src/Wpf.Ui/Controls/Interfaces/INavigation.cs | 6 ++----
src/Wpf.Ui/Controls/Navigation/NavigationBase.cs | 8 ++++----
src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs | 6 ++----
src/Wpf.Ui/Mvvm/Services/NavigationService.cs | 8 ++++----
src/Wpf.Ui/Services/Internal/NavigationManager.cs | 10 +++-------
9 files changed, 21 insertions(+), 29 deletions(-)
diff --git a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
index 28a139f78..80037cd82 100644
--- a/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
+++ b/src/Wpf.Ui.Demo/ViewModels/BreadcrumbPagesViewModel.cs
@@ -21,7 +21,7 @@ public BreadcrumbPagesViewModel(INavigationService navigationService)
private void OnClick(string pageTag)
{
- _navigationService.NavigateTo($"/{pageTag}", true, this);
+ _navigationService.NavigateTo($"/{pageTag}", this);
}
private void OnNavigateBack()
diff --git a/src/Wpf.Ui.Demo/Views/Container.xaml.cs b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
index b520f7ee3..aa02a4864 100644
--- a/src/Wpf.Ui.Demo/Views/Container.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Container.xaml.cs
@@ -98,10 +98,10 @@ public INavigation GetNavigation()
=> RootNavigation;
public void NavigateTo(Type type, object dataContext = null)
- => RootNavigation.NavigateTo(type, true, dataContext);
+ => RootNavigation.NavigateTo(type, dataContext);
public void NavigateTo(string pageTag, object dataContext = null)
- => RootNavigation.NavigateTo(pageTag, true, dataContext);
+ => RootNavigation.NavigateTo(pageTag, dataContext);
public void SetPageService(IPageService pageService)
=> RootNavigation.SetIPageService(pageService);
diff --git a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
index f13cc8e15..a1a574d82 100644
--- a/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Pages/Controls.xaml.cs
@@ -115,6 +115,6 @@ private void MessageBox_RightButtonClick(object sender, System.Windows.RoutedEve
private void OnBreadcrumbButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = _serviceProvider.GetRequiredService();
- _navigation.NavigateTo("/page1", true, viewModel);
+ _navigation.NavigateTo("/page1", viewModel);
}
}
diff --git a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
index d4d4b1dcc..a90b5fb71 100644
--- a/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
+++ b/src/Wpf.Ui.Demo/Views/Windows/ExperimentalWindow.xaml.cs
@@ -140,8 +140,8 @@ public void CloseWindow()
=> Close();
public void NavigateTo(Type type, object dataContext = null)
- => RootNavigation.NavigateTo(type, true, dataContext);
+ => RootNavigation.NavigateTo(type, dataContext);
public void NavigateTo(string pageTag, object dataContext = null)
- => RootNavigation.NavigateTo(pageTag, true, dataContext);
+ => RootNavigation.NavigateTo(pageTag, dataContext);
}
diff --git a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
index fa4bbe74a..1eeb093aa 100644
--- a/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
+++ b/src/Wpf.Ui/Controls/Interfaces/INavigation.cs
@@ -105,15 +105,13 @@ public interface INavigation
/// TODO
///
///
- ///
///
- void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null);
+ void NavigateTo(string pageTag, object? dataContext = null);
///
/// TODO
///
///
- ///
///
- void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null);
+ void NavigateTo(Type type, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
index 7200dfd21..4a29a17e9 100644
--- a/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
+++ b/src/Wpf.Ui/Controls/Navigation/NavigationBase.cs
@@ -251,16 +251,16 @@ public void SetIPageService(IPageService pageService)
public void ClearCache() => _navigationManager.ClearCache();
///
- public void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null)
+ public void NavigateTo(string pageTag, object? dataContext = null)
{
- if (_navigationManager.NavigateTo(pageTag, addToHistory, dataContext))
+ if (_navigationManager.NavigateTo(pageTag, dataContext))
OnNavigated();
}
///
- public void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null)
+ public void NavigateTo(Type type, object? dataContext = null)
{
- if (_navigationManager.NavigateTo(type, addToHistory, dataContext))
+ if (_navigationManager.NavigateTo(type, dataContext))
OnNavigated();
}
diff --git a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
index 23519cd3e..73bf29cfa 100644
--- a/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Contracts/INavigationService.cs
@@ -57,15 +57,13 @@ public interface INavigationService
/// Lets you navigate to the selected page based on it's tag. Should be used with .
///
/// Tag of the page.
- ///
///
- void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null);
+ void NavigateTo(string pageTag, object? dataContext = null);
///
/// TODO
///
///
- ///
///
- void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null);
+ void NavigateTo(Type type, object? dataContext = null);
}
diff --git a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
index 83e07a2bd..0d973fddc 100644
--- a/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
+++ b/src/Wpf.Ui/Mvvm/Services/NavigationService.cs
@@ -81,14 +81,14 @@ public void SetPageService(IPageService pageService)
}
///
- public void NavigateTo(string pageTag, bool addToHistory = true, object? dataContext = null)
+ public void NavigateTo(string pageTag, object? dataContext = null)
{
- NavigationControl.NavigateTo(pageTag, addToHistory, dataContext);
+ NavigationControl.NavigateTo(pageTag, dataContext);
}
///
- public void NavigateTo(Type type, bool addToHistory = true, object? dataContext = null)
+ public void NavigateTo(Type type, object? dataContext = null)
{
- NavigationControl.NavigateTo(type, addToHistory, dataContext);
+ NavigationControl.NavigateTo(type, dataContext);
}
}
diff --git a/src/Wpf.Ui/Services/Internal/NavigationManager.cs b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
index 7ef437760..78d7a3629 100644
--- a/src/Wpf.Ui/Services/Internal/NavigationManager.cs
+++ b/src/Wpf.Ui/Services/Internal/NavigationManager.cs
@@ -21,7 +21,6 @@ internal sealed class NavigationManager : IDisposable
private bool _isBackwardsNavigated;
private bool _addToNavigationStack;
- private bool _addToHistory = true;
public bool CanGoBack => History.Count > 1;
public readonly List History = new();
@@ -63,7 +62,7 @@ public void ClearCache()
}
}
- public bool NavigateTo(string tag, bool addToHistory, object? dataContext = null)
+ public bool NavigateTo(string tag, object? dataContext = null)
{
Guard.IsNotNullOrEmpty(tag, nameof(tag));
@@ -83,7 +82,7 @@ public bool NavigateTo(string tag, bool addToHistory, object? dataContext = null
return NavigateInternal(itemId, dataContext);
}
- public bool NavigateTo(Type type, bool addToHistory, object? dataContext = null)
+ public bool NavigateTo(Type type, object? dataContext = null)
{
var itemId = GetItemId(serviceItem => serviceItem.PageType == type);
if (itemId < 0)
@@ -171,10 +170,7 @@ private void AddToHistory(int itemId)
History.RemoveAt(History.LastIndexOf(History[History.Count - 1]));
}
- if (_addToHistory)
- History.Add(itemId);
-
- _addToHistory = true;
+ History.Add(itemId);
}
private bool CheckForNavigationCanceling(FrameworkElement instance)