Search code examples
c#desktop-applicationcode-behindnavigationviewwinui-3

With a NavigationView control, how can I navigate from the code behind?


is it possible to navigate from code-behind in a NavigationView? If I am one one page in the NavigationView's frame, and I want to leave that page and display another valid page, is this possible. My project is not in MVVM structure. I appreciate your help.

Here is my NavigationView:

<NavigationView x:Name="MasterNavigation"
                Header="Main"
                ItemInvoked="MasterNavigation_ItemInvoked" 
                PaneTitle="Menu"
                IsBackButtonVisible="Collapsed"
                IsSettingsVisible="False"
                PaneDisplayMode="Auto"
                OpenPaneLength="200"
                IsTabStop="True">
    
    <NavigationView.MenuItems>

        <NavigationViewItem Icon="Home"       Content="Home"                 Tag="home" IsSelected="True"/>
        <NavigationViewItem Icon="Globe"      Content="Data Collection"      Tag="datacollection"/>
        <NavigationViewItem Icon="Globe"      Content="Data Collection (v2)" Tag="collectdata"/>
        <NavigationViewItem Icon="Document"   Content="Goals"                Tag="goals"/>
        <NavigationViewItem Icon="Manage"     Content="Approvals"            Tag="approvals"/>
        <NavigationViewItem Icon="Print"      Content="Reports"              Tag="reports"/>
        <NavigationViewItem Icon="Admin"      Content="Admin"                Tag="admin"/>
        <NavigationViewItem Icon="PostUpdate" Content="Metric Staging"       Tag="metricstaging"/>
        <NavigationViewItem Icon="PostUpdate" Content="Ref Metric Main"      Tag="refmetricmain"/>
        <!--<NavigationViewItem Icon="Calculator" Content="Dashboard" Tag="dashboard" />-->

    </NavigationView.MenuItems>
    
    <Frame x:Name="MasterContentFrame" Margin="0,0,0,0"/>

</NavigationView>

This is the code I used to navigate via the UI:

        private void MasterNavigation_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
        {
            if (args.IsSettingsInvoked)
            {
                MasterContentFrame.Navigate(typeof(pageSettings));
            }
            else
            {
                // find NavigationViewItem with Content that equals InvokedItem
                NavigationViewItem item = sender.MenuItems.OfType<NavigationViewItem>().First(x => (string)x.Content == (string)args.InvokedItem);
                NavView_Navigate(item);
            }
        }

        private void NavView_Navigate(NavigationViewItem item)
        {
            switch (item.Tag)
            {
                case "home":
                    MasterContentFrame.Navigate(typeof(pageHome));
                    MasterNavigation.Header = item.Content;
                    break;

                case "datacollection":
                    MasterContentFrame.Navigate(typeof(pageDataCollection));
                    MasterNavigation.Header = item.Content;
                    break;

                case "collectdata":
                    MasterContentFrame.Navigate(typeof(PageCollectMetricData));
                    MasterNavigation.Header = item.Content;
                    break;

                case "goals":
                    MasterContentFrame.Navigate(typeof(pageGoals));
                    MasterNavigation.Header = item.Content;
                    break;

                case "approvals":
                    MasterContentFrame.Navigate(typeof(pageComments));
                    MasterNavigation.Header = item.Content;
                    break;

                case "reports":
                    MasterContentFrame.Navigate(typeof(pageReports));
                    MasterNavigation.Header = item.Content;
                    break;

                case "admin":
                    MasterContentFrame.Navigate(typeof(pageAdmin));
                    MasterNavigation.Header = item.Content;
                    break;

                case "metricstaging":
                    MasterContentFrame.Navigate(typeof(pageMetricStaging));
                    MasterNavigation.Header = item.Content;
                    break;

                case "refmetricmain":
                    MasterContentFrame.Navigate(typeof(pageRefMetricMain));
                    MasterNavigation.Header = item.Content;
                    break;
            }
        }

I have a button on the 'Metric Staging' page, where if clicked I would like it to open the 'Data Collection' page in the MasterContentFrame.

Here is the button event code, that is triggered when the button is clicked on the 'Metric Staging' page:

private void ButtonListViewEdit_Click(object sender, RoutedEventArgs e)
{
    Debug.WriteLine($"PAGE METRIC STAGING: BUTTON WAS CLICKED");
    // Below are my attempts to implement 'code-behind' navigation 
    //MetricReporting.MainWindow MasterContentFrame.Navigate(typeof(pageDataCollection));
    //MasterNavigation.Header = "Data Collection";
    //var navigation = (Application.Current as App).MasterNavigation;
}

Solution

  • You could set the x:FieldModifier attribute of the Frame element in the window to internal or public to be able to access the Frame from antother class:

    <Frame x:Name="MasterContentFrame" x:FieldModifier="internal" Margin="0,0,0,0"/>
    

    Also change the modifier for the m_window field in App.xaml.cs:

    internal Window m_window;
    

    You can then access the Frame from the event handler in the Page like this:

    private void ButtonListViewEdit_Click(object sender, RoutedEventArgs e)
    {
        MainWindow window = (App.Current as App)?.m_window as MainWindow;
        if (window != null)
        {
            window.MasterContentFrame.Navigate(typeof(typeof(pageDataCollection)));
        }
    }