Sep 28, 2011

Localize ToggleSwitch in Silverlight Toolkit

Read tons of blogs and questions and answers, but cannot get Localize ToggleSwitch in SilverLight Toolkit in my Windows Phone Application. So i decided to get my own way. My proposal based on DataTemplate for ToggleSwitch and ValueConverter. So let's go.

First add Localized Resource for our new On and Off string values:


Next step create ValueConverter:
  1. public class BoolToSwitchConverter : IValueConverter  
  2. {  
  3.     private string FalseValue = Resources.Off;  
  4.     private string TrueValue  = Resources.On;  
  5.   
  6.     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)  
  7.     {  
  8.         if (value == null)  
  9.             return FalseValue;  
  10.         else  
  11.             return ("On".Equals(value)) ? TrueValue : FalseValue;  
  12.     }  
  13.   
  14.     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)  
  15.     {  
  16.         return value != null ? value.Equals(TrueValue) : false;  
  17.     }  
  18. }  
Make our converter visible from XAML, adding glue code to Application Resources in App.xaml Add link to app namespace if you not do this before xmlns:local="clr-namespace:AppNamspace" And add resource code
  1. <Application.Resources>  
  2.     <local:BoolToSwitchConverter x:Key="Switch" />  
  3. </Application.Resources>  
And finally override DataTemplate on our ToggleSwitch:
  1. <toolkit:ToggleSwitch x:Name="MySwitch" Header="Localized Switch">  
  2.     <toolkit:ToggleSwitch.ContentTemplate>  
  3.         <DataTemplate>  
  4.             <ContentControl HorizontalAlignment="Left"   
  5.                 Content="{Binding Converter={StaticResource Switch}}"/>  
  6.         </DataTemplate>  
  7.     </toolkit:ToggleSwitch.ContentTemplate>  
  8. </toolkit:ToggleSwitch>  
Result:

Sep 26, 2011

Localize Windows Phone 7 Styles

In process of localize silverlight application, usually, localized text wider than original english. In most cases it not a problem if You use StackPanel or other wrapping conrols, but sometimes width cannot be easely changed. In silverlight application You can use satellite assembly and put localized styles, and connect to page using MergedDictionary and ResourceDictionary.

Why cannot use same approach for Windows Phone application? There is many reasons:

  1. Windows Phone don't support satellite assemblies.
  2. Windows Phone don't care about xml:lang
  3. MergedDictionary degrade preformance
So try to use another approach. Define control, Button for example and apply default style
  1. <Button x:Name="MyStyledButton" Content="Button" Style="{StaticResource MyButton}"/>  
Then put general style in App.xaml

  1. <Style x:Key="MyButton" TargetType="Button">  
  2.     <Setter Property="Background" Value="#303030"></Setter>  
  3.     <Setter Property="BorderThickness" Value="0"></Setter>  
  4. </Style>  

Another bug in Windows Phone 7 that attribute BasedOn not supported, so we have to copy whole style to derived. Next step change name, adding -[lang code] to x:Key of style. So 'MyButton' will be 'MyButton-de' for example.

  1. <Style x:Key="MyButton-ru" TargetType="Button">  
  2.     <Setter Property="Background" Value="#FF8080"></Setter>  
  3.     <Setter Property="BorderThickness" Value="1"></Setter>  
  4. </Style>  

Next we'll add runtime code for loading language dependent styles.

  1. string lang = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;  
  2. // load localized style  
  3. Style style = (Style)App.Current.Resources["MyButton-" + lang];  
  4. if (style != null)  
  5. {  
  6.     MyButton.Style = style;  
  7. }  

In runtime we determine current UI language and try to load altered style. If found, apply new style, if not - hardcoded style will be used.

Sep 6, 2011

Load Image at Background Thread in Silverlight WP7

Load image at background thread in Silverlight Windows Phone 7 application, is that possible?

Usually when you try to use BitmapImage, Image, WriteableImage in other than UI thread, you'll get exception. This is because these classes are derived from  System.Windows.Threading.DispatcherObject, which is blocked access from other than UI thread. There exists an extension to WriteableBitmap, LoadJpeg, which is works fine in thread, but you have to create WriteableBitmap object on main UI thread.


  1. using System.Windows;  
  2. using System.Windows.Media.Imaging;  
  3. using System.IO;  
  4. using System.Threading;  
  5.   
  6. namespace ImageHelpers  
  7. {  
  8.     public delegate void ImageLoadedDelegate(WriteableBitmap wb, object argument);  
  9.   
  10.     public class ImageThread  
  11.     {  
  12.         public event ImageLoadedDelegate ImageLoaded;  
  13.   
  14.         public ImageThread()  
  15.         {  
  16.         }  
  17.   
  18.         public void LoadThumbAsync(Stream src, WriteableBitmap bmp, object argument)  
  19.         {  
  20.             ThreadPool.QueueUserWorkItem(callback =>  
  21.             {  
  22.                 bmp.LoadJpeg(src);  
  23.                 src.Dispose();  
  24.                 if (ImageLoaded != null)  
  25.                 {  
  26.                     Deployment.Current.Dispatcher.BeginInvoke(() =>  
  27.                     {  
  28.                         ImageLoaded(bmp, argument);  
  29.                     });  
  30.                 }  
  31.             });  
  32.         }  
  33.     }  
  34. }  


Using scenario:

  1. ImageThread imageThread = new ImageThread();  
  2.   
  3. private void Init()  
  4. {  
  5.     imageThread.ImageLoaded += LoadFinished;  
  6. }  
  7.   
  8. void LoadFinished(WriteableBitmap bmp, object arg)  
  9. {  
  10.     Imgage1.Source = bmp;  
  11. }  
  12.   
  13. void DeferImageLoading( Stream imgStream )  
  14. {  
  15.     // we have to give size  
  16.     var bmp = new WriteableBitmap(80, 80);  
  17.     imageThread.LoadThumbAsync(imgStream, bmp, this);  
  18. }