Corrado's Blog 2.0

Online thoughts of a technology funatic

Dynamic localization of Windows Store apps

Localizing a Windows Store app is a fairly easy task thanks to the x:UId attribute introduced with WinRT.
If you need to create a Multilanguage application just add to your Visual Studio solution a folder named Strings and below it add a folder for each language you want to support using the two letter ISO language as name.
In this picture I have a solution that support Italian and American English

image

Inside each folder I’ve added a resource file and note that there’s a Resource.resw file just below Strings folder, it represent the default fallback resource language file that will be used in case your app will be executed on a system whose language is different than America English or Italian.

Inside each Resource.resw add the property of the control to localize, in our case we want to localize the Text property of a TextBlock, so the file content for each will be:

en-US folder

image

it-IT folder

image

Now to localize the Text property of our TextBlock all we need to to is use this XAML:

1 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 2 <TextBlock x:Uid="WelcomeMessage" 3 VerticalAlignment="Center" 4 Foreground="BlueViolet" 5 Text="..." 6 HorizontalAlignment="Center" 7 FontSize="48" /> 8 </Grid>

Here’s what you’ll see when the code is executed on an Italian pc:

image

Very easy isn’t it? Smile

This approach let you do more than just localize Text, if you want to dig more into it you can read this article

Ok, but imagine you have this mandatory requests:

  • 1-Application language can be unrelated to machine language (French app running on an Italian machine)

2-Language switching should not require an application reboot

3-You must use a MVVM friendly solution

Ok, things can get a little more intricate here  and since I haven’t found a standard solution I solved this way:

Step 1: Since we’ll deal with text only let’s rename resources inside .resw files from WelcomeMessage.Text to just WelcomeMessage (see below)

image

Step 2: Let’s create a ViewModel (yes, MVVM always requires a ViewModel…) and let’s add the necessary code to load the strings dynamically:

1 public class MyViewModel : INotifyPropertyChanged 2 { 3 private ResourceContext resoureContext; 4 5 public MyViewModel(string language) 6 { 7 this.UpdateCulture(language); 8 } 9 10 public void UpdateCulture(string language) 11 { 12 this.resoureContext = ResourceContext.GetForCurrentView(); 13 this.resoureContext.Languages = new List<string> { language }; 14 } 15 16 public string GetResource(string stringResource) 17 { 18 try 19 { 20 var resourceStringMap = ResourceManager.Current.MainResourceMap.GetSubtree("Resources"); 21 return resourceStringMap.GetValue(stringResource, this.resoureContext).ValueAsString; 22 } 23 catch (Exception ex) 24 { 25 return $"?{stringResource}?"; 26 } 27 } 28 29 ... 30 }

The magic here is inside UpdateCulture and GetResource methods, if we name the TextBlock in previous XAML snippet MyTextBlock we can dynamically change its text using this code:

1 public sealed partial class MainPage : Page 2 { 3 public MainPage() 4 { 5 this.InitializeComponent(); 6 this.MyTextBlock.Text = new MyViewModel("it-IT").GetResource("WelcomeMessage"); 7 8 } 9 }

But since we’re using MVVM we want to use databinding for that instead of code and we need a smart solution otherwise localization can become tedious, solution is not very far: just use an indexer:

Just add this line of code to the ViewModel

1 public string this[string key] => this.ApplicationController.GetResource(key);

And let’s inform binding that our indexer property need to be refreshed so that all texts will be reloaded when user changes the UI language at runtime modifying the UpdateCulture method this way:

1 public void UpdateCulture(string language) 2 { 3 this.resoureContext = ResourceContext.GetForCurrentView(); 4 this.resoureContext.Languages = new List<string> { language }; 5 this.OnPropertyChanged("Item[]"); 6 }

Note the trick of using “Item[]” as property name to signal that the class indexer has changed.

So let’s bind TextBlock’s Text property to viewmodel indexer using this syntax, and you’re done.

1 <TextBlock x:Name="MyTextBlock" 2 VerticalAlignment="Center" 3 Foreground="BlueViolet" 4 Text="{Binding [WelcomeMessage]}" 5 HorizontalAlignment="Center" 6 FontSize="48" />

You can find a complete example here.

Have fun!

Windows 8: Is app running inside Visual Studio?

Sometimes you need to run some additional debugging code when your app is launched from a development environment (e.g from Visual Studio), of course there are compiler directives for this but I’ve found a property inside WinRT that can make this even easier.

bool isInsideVs = Windows.ApplicationModel.Package.Current.IsDevelopmentMode;

please note that property indicates Development mode, this means that it will probably check whether app is running from \Program Files\WindowsApps folder so if you launch the just compiled app from Start menu on same machine it will still returns true.

Try to sideload the app and in this case it will have the value false.

 

The tale of a GridViewItem customization

Once upon a time, in a galaxy not so far away, there was a guy (me Smile) who was working on a Windows Store 8.1 application and was asked to create a GridView whose items should look like this picture:

image

The guy (again, me) thought: What’s the problem, did it many times! and he started setting a data source:

public class Item
    {
        public string Text { get; set; }
    }

    public class DemoViewModel
    {
        public DemoViewModel()
        {
            this.Items = new List<Item>();
            for (int i = 0; i < 10; i++)
            {
                this.Items.Add(new Item() { Text = "Item " + i });
            }
        }

        public IList<Item> Items { get; set; }
    }

He then added a GridView to a page, bound the data source and created a simple ItemTemplate:

<Page x:Class="GridViewDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:GridViewDemo"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
    <Page.Resources>
        <local:DemoViewModel x:Key="vm"></local:DemoViewModel>
        <DataTemplate x:Key="MyItemTemplate">
            <Grid Width="100"
                  Height="60">
                <TextBlock HorizontalAlignment="Center"
                           TextWrapping="Wrap"
                           Text="{Binding Text}"
                           VerticalAlignment="Center" />
            </Grid>
        </DataTemplate>
        
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          DataContext="{StaticResource vm}">
        <GridView ItemsSource="{Binding Items}"
                  ItemTemplate="{StaticResource MyItemTemplate}"
                   />
    </Grid>
</Page>

Run the solution and he got something quite close to what he was asked to realize:

image

Ok, just a couple of customizations and we’re done, he thought…

Let’s start with the selected background: The guy knows that background brush is managed inside ItemContainerStyle so he fired up Blend 2013, edited GridView’s ItemContainerStyle and here’s what he got:

image

Just a simple GridViewItemPresenter that has a series of Brush properties that give you the opportunity to customize several container aspects

image

In his case he needed to customize the color of SelectedBackground so, since it is bound to a resource named ListViewItemSelectedBackgroundThemeBrush he added a Brush resource with the same name inside Page resources and selected state was done, here’s updated result:

<SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush"
                         Color="Orange"></SolidColorBrush>

image

But a question started to rise in his mind: “How to i set default (gray) background color?” there’s no Background color exposed by GridViewItemPresenter nor he can set it inside ItemTemplate otherwise it wouldn’t change when item is selected.

He tried lookind inside MSDN docs hoping to find a brush key that controls item default background but he had no luck Sad smile and navigated a lot the Internet until he realized he did something similar in the past for a Windows 8.0 application.

He then opened that old source code and discovered what has changed: The GridViewItemPresenter has been introduced in Windows 8.1, here’s how ItemContainerStyle looks in Windows 8.0:

image

Since you have access to all the elements composing the GridViewItem what the guy did was copying the style into Windows 8.1 app and edited VisualStateManager states (I’m sure, dear reader, you know how to do that…)

So, here’s final result:

image

The guy secretly told me that he wasn’t happy for such solution, probably GridViewItemPresenter has been introduced to improve GridView’s performances but he found no other easier way to solve the puzzle.

Based on a true story… Smile

PS: In case you need Windows 8.0 GridView’s ItemContainerStyle you can get it here.

The remote procedure call failed. Exception from HRESULT: 0x800706BE issue in Windows Store apps

There are days where technology seems to be against you, yesterday was one of those.

It all started in the morning when I inadvertently pressed the sleep button on my Logitec keyboard and my notebook gone into sleep mode, something i do often indeed, but this time it was different because at resume all i got was a black screen. Since this happened a couple of times in the past I switched it off hoping to solve it soon, but after machine boot the black screen was still there. A voice inside of me started saying “is gonna be a hard day…”, so i started, without much faith honestly the: boot, safe mode, repair, try restore point ritual but, as always happened in my personal experience, without luck.

Since I really hate repaving my work machine, I’m a bit paranoid with backups: I do backup at least once/twice a week and before any important update. so I inserted the USB recovery key of my favorite’s backup tool: Acronis True Image and started a sector-by-sector restore of July 28th backup.

After a while my notebook was brought back to life, and nobody will ever know what happened on this bright July 30th morning, but who cares, it’s time to go back coding…

Since I’m working on a Windows Store app that interacts with Facebook I started digging into Facebook SDK documentation and in short time I wrote a test app that logins and retrieves user profile.

Time to test the code: I lanched the app, the login dialog appeared and successfully logged in, but, wait, there’s a an issue: the breakpoint I added to read the returned token didn’t fired and application seems never returning from Login method.

Ok, let’s find what’s wrong but starting from Facebook developer registration down to code everything looks fine.

Let’s try an old sample I wrote in the past I know was ok: same problem.

Let’s use WebAuthenticationBroker sample from Developer portal, it must work!: well it wasn’t.

Since I lost any idea I asked my friend @CristianCivera some hints and you can image my face when after some pair debugging he told me: “Know what? the sample works on my machine

Below my face as soon as I read the message:

Also my friend @imperugo confirmed: The only machine on earth where the WebAuthenticationBroker.AuthenicateAsync() method was not returning was mine…

Just to be 100% sure I started a remote debugging session with my tablet and everything was working as expected.

I started to getting nervous since I had no idead why that call wasn’t working on my PC.

While trying to find a solution i thought: And if problem isn’t in just WebAuthenticationBroker but in all async methods? So I opened the FilePicker example from Windows Store dev portal, launched it and put a breakpoint on yellow line:

image

Result: I can select the file, breakpoint doesn’t fire anyway,  but now Visual Studio reports an exception:

The remote procedure call failed. (Exception from HRESULT: 0x800706BE)"}

a search on Interned pointed me to several possible solutions but none was the right one, looks like async call for unknown reason never returns, even launching the standalone app..

I started realizing that can’t work on any Windows Store app until I get this fixed and wondered: Why didn’t got into this before?, I spend the day between async/await and breapoints always worked.

Tried another Windows Store app that uses async/await and breakpoints worked, so why some async calls raise the exception and others don’t?

After long thinking I realized that both OpenPicker.PickSingleFileAsync() and WebAuthenticationBroker.LoginAsync() deal with UI, former opens file selection while latter displays a dialog, so I started thinking about graphic drivers (don’t ask me why, maybe someone took pity on me…) so I updated my NVidia driver and restarted.

No way, problem still there…

Before starting to tear my hair (and remind me that I do not have…) i remembered that I also have a USB video driver that controls my 3rd monitor: A quick check and saw that it driver was outdated, so i installed the recent one. Rebooted the machine launched the sample and…

YESSSSSS!!! The problem gone! probably something in the driver was conflicting with WinRT causing the exception thus preventing the call to return.

To recap this long post: If your async calls seems not to return and you get weird: The remote procedure call failed. (Exception from HRESULT: 0x800706BE)" message: check your video drivers.

If all this sound unbeliveable, you’re right, IT IS! (while true…)

Hope this will save you working hours (and hairs) in future.

How to uniquely identify a Windows 8 device from WinRT

There are some cases where you need to identify a precise Windows 8 device (imagine a subscription that’s locked to a specific machine), in Windows Phone you could use:

Microsoft.Phone.Info.DeviceExtendedProperties.GetValue( "DeviceUniqueId" );

Unfortunately that was not available in WinRT but good new is that capability has been added into final release:

Windows.System.Profile.HardwareIdentification.GetPackageSpecificToken(null);

is all you need to get the identifier tied to a machine.

source: stackoverflow