I have started to work with WinUI 3, the new UI tech from Microsoft.
My question is similar to this one WinUI 3.0 Desktop - C# Page Navigation, but I specifically want to know about navigating to existing page instances.
My application's main menu consists of a NavigationView control.
Remark: I installed this sample solution ("xaml-controls-gallery") in order to learn its basic concepts.
Currently I have 3 instances of NavigationViewItem inside it:
<NavigationView x:Name="navigationView" PaneDisplayMode="Top"
SelectionFollowsFocus="Enabled" IsBackButtonVisible="Collapsed" ItemInvoked="NavigationView_OnItemInvoked"
>
<NavigationView.MenuItems>
<NavigationViewItem Icon="Play" Content="Menu 1" x:Name="Menu1Item" Tag="Page1" />
<NavigationViewItem Icon="Filter" Content="Menu 2" x:Name="Menu2Item" Tag="Page2"/>
<NavigationViewItem Icon="Refresh" Content="Menu 3" x:Name="Menu3Item" Tag="Page3" />
</NavigationView.MenuItems>
<!-- The section will contain the content for selected navigation item -->
<Grid Padding="20">
<Frame x:Name="rootFrame" Navigated="RootFrame_OnNavigated"/>
</Grid>
</NavigationView>
The content that belongs to the respective menu item shall be shown in the Frame "rootFrame". For the content I have created Page classes: Page1, Page2 and Page3.
In the code behind file, I handle the "ItemInvoked" event of the NavigationView. I check the "Tag" of the NavigationItem and set the type of the Page I want to navigate to.
private void NavigationView_OnItemInvoked(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewItemInvokedEventArgs args)
{
FrameNavigationOptions navOptions = new FrameNavigationOptions();
navOptions.TransitionInfoOverride = args.RecommendedNavigationTransitionInfo;
string navItemTag = args.InvokedItemContainer.Tag.ToString();
Type pageType = null;
if (navItemTag == "Page1")
{
pageType = typeof(Page1);
}
else if (navItemTag == "Page2")
{
pageType = typeof(Page2);
}
else if (navItemTag == "Page3")
{
pageType = typeof(Page3);
}
if (pageType == null)
{
return;
}
rootFrame.NavigateToType(pageType, null, navOptions);
}
However calling "NavigateToType" on the Frame instance always creates a new instance of the page class. What I want, is not to loose that state of the page where the user has also made some changes to the UI. So I want to navigate to the already existing instance of the page.
I do not know how to accomplish this.
As a consequence in the "OnNavigatedTo" event of the page the NavigationMode of the "e" parameter is always NavigationMode.New instead of NavigationMode.Refresh. Here an example for "Page1":
public sealed partial class Page1 : Page
{
public Page1()
{
this.InitializeComponent();
ViewModel = new Page1ViewModel();
// Load data (expensive operation)
}
public Page1ViewModel ViewModel { get; set; }
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// e.NavigationMode is always NavigationMode.New
// How do we get NavigationMode.Refresh?
}
}
Does someone know how to navigate to an existing page instance?
As a workaround I tried simply swapping the content of the frame directly:
rootFrame.Content = instanceOfPage;
But I do not really want to do this, because this bypasses the frame based navigation and also does not show an animation when navigating to the other page.
It seems that in WPF and the "old" .NET framework there was a class NavigationWindow which served this purpose, but this does not exist (yet) in WinUi.
CodePudding user response:
Set the NavigationCacheMode property of the pages to Required
or Enabled
:
<Page
x:Class="WinUI3App.Page1"
NavigationCacheMode="Enabled"
...
See also this article: Implement navigation between two pages - 4. Cache a page