Search code examples
c#xamluwpwin-universal-app

Navigating to specific ContentFrame when refreshing NavigationView


I have an app which uses a NavigationView as a UI-control.

Now I have a SettingsPage where I can change the language of my UI between german and english.

I change the language with this code:

public static void German()
    {
        Log.Logger.Information("Language = German")

        ApplicationLanguages.PrimaryLanguageOverride = "de-DE";
        DataCollection.Current.LanguageChangedEvent.LanguageChanged();
    }

The last line invokes an EventHandler which in turn invokes the following event on the MainPage.xaml.cs where the NavigationView is located.

public void ChangedLanguage(object source, EventHandlerBase e)
    {
        if (e.GetStatus())
        {

            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();

            Frame.Navigate(this.GetType());

            ContentFrame.Navigate(typeof(SettingsPage));
        }
    }

As it's possible to see I just want to return the user to the SettingsPage after changing the language. But I always return back to the initial HomePage that I use when starting the app.

The code I use for the NavigationView is derived from the official NavigationView sample provided by Microsoft.

Is there any possible way to do this? The only possible thing I can imagine is to set a flag after the first page loading and then always check if that flag is set. But then I have the problem that I still could only land at the SettingsPage because I would have to make it the else destination for the flag-check.

Would really appreciate a more dynamic way if thats even possible :/

Greeting, Daniel


Solution

  • The NavigationView sample just is a simple code sample for your reference. You need to make some changes by your requirements.

    I just want to return the user to the SettingsPage after changing the language. But I always return back to the initial HomePage that I use when starting the app.

    I've used the code on the document to make a code sample for testing. There're two places will cause your question.

    First, in the NavView_Loaded event handler, it will always sets the home page as the selected item. But when you change the language, you re-navigate to 'MainPage' and make 'ContentFrame' navigate to 'SettingsPage'. At this time, the On_Navigated event handler will be first called. Then, the NavView_Loaded event handler will be called. That's the reason why your app always will return to home page.

    Second, event if the NavigationView's SelectedItem has been set. But the NavigationView's ItemInvoked event will not be fired. So, what you see actually is not home page, it's a blank Frame control. You could use SelectionChanged event instead of ItemInvoked event. The SelectionChanged event will be fired when you set a new value for the NavigationView's SelectedItem. See the following sample:

    private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
    {
        if (args.IsSettingsSelected)
        {
            ContentFrame.Navigate(typeof(SettingsPage));
        }
        else
        {
            NavView_Navigate(args.SelectedItem as NavigationViewItem);
        }
    }
    

    Then, let's back to your original question:

    I can imagine is to set a flag after the first page loading and then always check if that flag is set. But then I have the problem that I still could only land at the SettingsPage because I would have to make it the else destination for the flag-check.

    In my opinion, the flag will not affect you doing other things. You completely could define several flags. Please see my following code snippet for reference:

    public static void German()
    {
        Log.Logger.Information("Language = German")
        ApplicationLanguages.PrimaryLanguageOverride = "de-DE";
        ApplicationData.Current.LocalSettings.Values["IsSwitchingLanguage"] = true;
        DataCollection.Current.LanguageChangedEvent.LanguageChanged();
    }
    

    In your MainPage.xaml.cs:

    public void ChangedLanguage(object source, EventHandlerBase e)
    {
            if (e.GetStatus())
            {
                Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
                Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
                Frame.Navigate(this.GetType());
    
            }
    }
    

    In NavView_Loaded event handler, I made some changes:

    private void NavView_Loaded(object sender, RoutedEventArgs e)
    {
            ...... 
            foreach (NavigationViewItemBase item in NavView.MenuItems)
            {
                var IsSwitchingLanguage = ApplicationData.Current.LocalSettings.Values["IsSwitchingLanguage"];
                if (IsSwitchingLanguage != null)
                {
                    if ((bool)IsSwitchingLanguage)
                    {
                        NavView.SelectedItem = NavView.SettingsItem as NavigationViewItem;
                        ApplicationData.Current.LocalSettings.Values["IsSwitchingLanguage"] = false;
                        break;
                    }
    
                }
                if (item is NavigationViewItem && item.Tag.ToString() == "home")
                {
                    NavView.SelectedItem = item;
                    break;
                }
            }
    
            ......
    }