开发者

How to switch UI Culture of data binding on the fly in Silverlight

I have a TextBlock control, which is data bound to DateTime property.

The text displayed something like this:

Thursday, October 21, 2010

I need to switch UI Culture on the fly, using something like this:

Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.Cu开发者_StackOverflowrrentUICulture 
                                    = new CultureInfo("de-de");

I've tried this to force binding to recalc:

var bindingExpression = textBlock.GetBindingExpression(TextBlock.TextProperty);
bindingExpression.UpdateSource();

But I still see Thursday instead of Donnerstag...

How do I proceed? Any ideas?


I've found a better approach, which requires to update only the root visual.

public sealed class Localizer : INotifyPropertyChanged
{
  public Localizer() 
  {
    Culture = Thread.CurrentThread.CurrentCulture; 
  }

  XmlLanguage _language;
  public XmlLanguage Language 
  { 
    get { return _language; } 
    private set { _language = value; RaiseOnPropertyChanged("Language"); } 
  }

  CultureInfo _culture;
  public CultureInfo Culture 
  { 
    get { return _culture; }
    set 
    { 
      Contract.Requires(value != null);  

      if (_culture == value) return; 
      _culture = value; 

      Thread.CurrentThread.CurrentCulture =
      Thread.CurrentThread.CurrentUICulture = value;
      Language = XmlLanguage.GetLanguage(value.Name);

      RaiseOnPropertyChanged("Culture");
    }
  }

  protected void RaiseOnPropertyChanged(string propName) 
  {
    var e = OnPropertyChanged;
    if (e != null) e(this, new PropertyChangedEventArgs(propName));
  }

  public event PropertyChangedEventHandler OnPropertyChanged;
}

Now adding this instance to application resources:

<nt:Localizer x:Key="Localizer"/>

Now bind it to your root visual (f.e. Frame, UserControl or Page) like this:

<UserControl ... Language="{Binding Language, Source={StaticResource Localizer}}">


You can use the following converter:

public class StringFormatter : IValueConverter
{

    public String Format { get; set; }
    public String Culture { get; set; }


    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!String.IsNullOrEmpty(Culture))
        {
            culture = new System.Globalization.CultureInfo(Culture);
        }
        else
        {
            culture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        }
        if (value == null) { return value; }
        if (String.IsNullOrEmpty(Format)) { return value; }
        return String.Format(culture, Format, value).Trim();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Then you can set the CurrentUICulture and force the binding to change and the converter will use the new culture.

If you want to display the date in long format, declare the converter in XAML like this:

<local:StringFormatter x:Key="LongDateFormatter" Format=" {0:D}" />

And then use it in your TextBlock like this:

<TextBlock x:Name="DateText" Text="{Binding DateTime.Date, Converter={StaticResource LongDateFormatter}, Mode=OneWay}"/>

In code you can do something like this to force the binding to change:

Thread.CurrentThread.CurrentUICulture = new CultureInfo(desiredCultureString);
var tempDateTime = this.DateTime;
this.DateTime = default(DateTime);
this.DateTime = tempDateTime;

Of course there are other ways to force the change, and probably you need to change other fields to the new culture as well, but this is the general idea of how to handle it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜