nsds
nsds

Reputation: 981

Change the app language programmatically - UWP

I have created resource files (.resw) for French and English. Now I want to call resource file for "fr" on loading the first page of my app. I have done like below. But it shows an exception

"System.NullReferenceException: Object reference not set to an instance of an object".

XAML

<TextBlock x:Uid="txt_launch3" Grid.Row="4"  Padding="7"/>

Code-behind

public sealed partial class MainPage : Page
{
    public MainPage()
    {    
       this.InitializeComponent();
       string getDeviceDefaultLang="fr";
       ChangeLanguage2(getDeviceDefaultLang);    
    }

    private void ChangeLanguage2(string language)
    {
        try
        {
            ApplicationLanguages.PrimaryLanguageOverride =language;
            Frame.CacheSize = 0;
         Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();          Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
            Frame.Navigate(this.GetType());
        }
        catch (Exception ex)
        {
            string exx = ex.ToString(); //getting System.NullReferenceException            
        }
    }
 }

Upvotes: 1

Views: 1056

Answers (1)

Martin Zikmund
Martin Zikmund

Reputation: 39072

The problem is that you are calling the method too early within the page. In the constructor the page is not yet assigned to the Frame it resides in. Because of this the Frame is still null there.

You could move the method call to the OnNavigatedTo override:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    string getDeviceDefaultLang = "fr";
    ChangeLanguage2(getDeviceDefaultLang);
}

private void ChangeLanguage2(string language)
{
    try
    {
        ApplicationLanguages.PrimaryLanguageOverride = language;
        Frame.CacheSize = 0;
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
        Frame.Navigate(this.GetType());
    }
    catch (Exception ex)
    {
        string exx = ex.ToString(); //getting System.NullReferenceException            
    }
}

Alernatively you could directly access the root frame of the app instead of through the Frame property of the page:

private void ChangeLanguage2(string language)
{
    try
    {
        ApplicationLanguages.PrimaryLanguageOverride = language;
        var rootFrame = Window.Current.Content as Frame;
        rootFrame.CacheSize = 0;
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
        Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();
        rootFrame.Navigate(this.GetType());
    }
    catch (Exception ex)
    {
        string exx = ex.ToString(); //getting System.NullReferenceException            
    }
}

However, this is really not optimal, because you are essentially navigating while there is an navigation currently taking place (the original MainPage navigation.

Most likely you will call the change language in response to user action anyway (like button click), when none of this will be a problem anymore and Frame will be defined.

Update

The best solution would be to set the language override in the OnLaunched handler in App.xaml.cs:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (e.PrelaunchActivated == false)
    {
        if (rootFrame.Content == null)
        {
            ApplicationLanguages.PrimaryLanguageOverride = "fr";
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForCurrentView().Reset();
            Windows.ApplicationModel.Resources.Core.ResourceContext.GetForViewIndependentUse().Reset();

            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }
        // Ensure the current window is active
        Window.Current.Activate();
    }
}

Upvotes: 2

Related Questions