Silverlight Quick Tip: Resources in RESX files – Image Resources for Localization

July 14, 2009

This post was actually born in the middle of previous post :)


I had to find the way to use images as a RESX resources – this actually was second question of the person who asked me about forcing the rebinding.


Before starting, some theory about RESX usage in Silverlight.


Silverlight support usage of RESX files and localization via “SupportedCultures” attribute in CSPROJ file. The attribute itself even exists in project created with Silverlight 3  Tools, but for some reason there is no interface to change the cultures (or at least I didn’t found them). So the only way (for me) to change this attribute is via text editing the CSPROJ file.

<SupportedCultures>
de,he,ru
</SupportedCultures>

After this attribute set, if we will use RESX files with standard .NET localization naming convention (<RESOURCE_NAME>.resx for culture neutral resources and <RESOURCE_NAME>.<LANGUAGE>.resx for language depended resorces) Visual Studio will compile resources and will create satellite assemblies for supported cultures.


I’ve added new “Resource” file to my project, and \added string values for HE, RU and DE languages. The 4th resource file is Neutral Culture (in my case EN) resources


image


imageimage


Here is first quick tip:



  • Change Access Modifier of your resources to “Public”, otherwise Silverlight will not be able to use it. image

Second tip:



  • Change access modifier of constructor in auto generated Resource class from internal to public (in my case the generated file was Strings.Designer.cs):
    internal Strings() -> public Strings()

The usage of those resources is very easy – simple StaticResource declaration in XAML and usage:

<Canvas.Resources>
<
local:Strings x:Key=”res”/>
</Canvas.Resources>
<
StackPanel x:Name=”LayoutRoot” Orientation=”Vertical”>
<
TextBlock x:Name=”txtSTR1″ Text=”{Binding tb1, Source={StaticResource res}}” FontSize=”15″ Foreground=”Black”/>
</StackPanel>

This way the text displayed in TextBlock will depend on Thread.CurrentThread.CurrentUICulture value or on “uiculture” parameter for Silverlight plug-in:

<param name=”uiculture” value=”de” />

To see how to force re-binding when Thread.CurrentThread.CurrentUICulture value changes at the runtime – see this post.


Now to the main issue – when trying to add any non-textual resource to the resource file visual studio will generate wrong code in the Designer file:


image


For Image(of any kind)/Icon/Existing File (of image type) it will generate following code:

public static System.Drawing.Bitmap img1
{
get
{
object obj = ResourceManager.GetObject(“img1″, resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}

The “System.Drawing.Bitmap” does not exists in Silverlight, thus the application will not compile. From other hand, if Visual Studio will not identify the resource (unknown resource type) it will generate following code:

public static byte[] img1 {
get {
object obj = ResourceManager.GetObject(“img1″, resourceCulture);
return ((byte[])(obj));
}
}

This is much better :)


Third tip:



  • Before you adding the image resource to Silverlight resources rename them

  • Alternatively you left the file name as it was and edit RESX file in text editor as follows:
<data name=”img1″ type=”System.Resources.ResXFileRef, System.Windows.Forms”>
<
value>Resources\MVP_small.png;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</
data>

Now the usage of this resource is very simple – all we need is a converter to convert byte[] to BitmapImage (in case of images). Here the converter:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
byte[] arr = (byte[])value;

MemoryStream str = new MemoryStream(arr);
BitmapImage img = new BitmapImage();
img.SetSource(str);
return img;
}


And usage (ByteArrConverter defined in Resources):

<Image x:Name=”img” Width=”100″ Height=”100″ Source=”{Binding img1, Source={StaticResource res},
Converter={StaticResource ByteArrConverter}}” Margin=”5″/>

Now image will be displayed on page, and it will will depend on Thread.CurrentThread.CurrentUICulture value or on “uiculture” parameter for Silverlight plug-in:


image


image


Live demo here


Sources here

 

Enjoy,


Alex

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

15 comments

  1. FRegerJuly 24, 2009 ב 13:52

    THANKS!!!!!!!!!!!!

    Reply
  2. slyiAugust 22, 2009 ב 12:43

    Handy method btw you can edit the your supportedcultures eg:

    1. In Solution Explorer
    2. Right Click on your silverlight project folder
    3. Select unload project
    4. Right click on your project
    5. Select Edit {Myproject} eg: “Edit SL3Loc.csproj”
    6. Edit the supported cultures element and save
    7. Right click on your project and select reload project

    Reply
  3. slyiAugust 22, 2009 ב 12:50

    BTW changing your contrustor to public is not recommended as the it break each time you edit the resx file. Instead use a class to make your resourse public. eg http://msdn.microsoft.com/en-us/library/dd882554(VS.95).aspx

    Reply
  4. anciiFebruary 18, 2010 ב 12:58

    Above concept is not working for DataGrid Header.

    HeaderStyle="{StaticResource DataGridBaseHeaderStyle}">

    Code is throwing exception…..

    Does DataGrid supports this feature of taking header name from Resource file if yes how can we implement that?????

    Reply
  5. Morten GrøtanMarch 18, 2010 ב 16:03

    ancii: DataGrid header localization requires a totally different approach: http://forums.silverlight.net/forums/t/37899.aspx

    Reply
  6. FabaSeptember 8, 2010 ב 17:46

    good article. thanks)

    Reply
  7. Tomasz WisniewskiFebruary 4, 2011 ב 9:50

    Hmm, after adding a new image to the resources file I can’t rebuild my solution because there is an error saying that the solution already contains a definition of MyClassName

    Reply
  8. kailash kuteMay 25, 2011 ב 11:46

    hi,
    greetings for the day
    i created strings.resx and strings.ja.resx
    but my silverlight textblock shows only english content from strings.resx but its not showing japanese content from strings.ja i have also mentioned the ja-JP in uiculture of aspx page but it doesnt show the japanese content from strings.ja.resx

    Reply
  9. Alex GoleshMay 25, 2011 ב 11:52

    Please check what is a culture of you thread (CurrentUICulture).

    Best,
    Alex

    Reply
  10. kailash kuteMay 25, 2011 ב 13:46

    i get following error

    Culture is not supported.
    Parameter name: name
    ja-JP is an invalid culture identifier.

    when i set the culture like below
    System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(“ja-JP”);

    Regards
    Kailash kute

    Reply
  11. Alex GoleshMay 25, 2011 ב 14:17

    Can you share the repro? Seems like you missing something small…

    //Alex

    Reply
  12. SwapnilJuly 9, 2011 ב 9:45

    What if i have to change the language on a button click event.suppose i have 2 buttons one for english and another for portuguese Cliking on any one will change the applications labels content accordingly.

    Reply