views:

416

answers:

1

I have a business application (created from template) and I can change language dynamically by making ResourceWrapper INotifyPropertyChanged and then adding in code:

private void Language_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
 Thread.CurrentThread.CurrentCulture =
     new CultureInfo(((ComboBoxItem)((ComboBox)sender).SelectedItem).Tag.ToString());
 Thread.CurrentThread.CurrentUICulture =
     new CultureInfo(((ComboBoxItem)((ComboBox)sender).SelectedItem).Tag.ToString());
 ((ResourceWrapper)App.Current.Resources["ResourceWrapper"]).ApplicationStrings =
     new ApplicationStrings();
}

this works fine on resources referenced/binded in xaml files (i.e. MainPage frame), but it does not update references of anything I have declared in code i.e.

InfoLabel.Content = ApplicationStrings.SomeString

At the moment I'm not using ResourceWrapper. My question here is how can I change my code so it uses it and updates when ResourceWrapper change. I tried:

InfoLabel.Content = ((ResourceWrapper)App.Current.Resources["ResourceWrapper"])
    .ApplicationStrings.SomeString

but it doesn't work.

Any ideas?

+1  A: 

You would have to create a Binding in code. Something like this:

var b = new Binding("SomeString");
b.Source = ((ResourceWrapper)App.Current.Resources["ResourceWrapper"]).ApplicationStrings;
b.Mode = BindingMode.OneWay;
InfoLabel.SetBinding(ContentControl.ContentProperty, b);

Keep in mind that the class you bind to must implement INotifyPropertyChanged.



EDIT: If you are worried about the amount of code, just create a helper method somewhere in your app:

public Binding GetResourceBinding(string key)
        {
            var b = new Binding(key);
            b.Source = ((ResourceWrapper)App.Current.Resources["ResourceWrapper"]).ApplicationStrings;
            b.Mode = BindingMode.OneWay;

            return b;
        }

And then use the helper method like this:

InfoLabel.SetBinding(ContentControl.ContentProperty, GetResourceBinding("SomeString"));
Henrik Söderlund
That seems to be an awful lot of work for such a simple thing. If I'd have to do it for every string I want to bind in code I'd probably use NavigationService.Refresh(), but this isn't visually elegant...
Artur
You are right, it is a lot of code. Which is why it is best to avoid it and declare your bindings directly in the XAML. Is there a reason why you have to set the text of the contentcontrol in code?
Henrik Söderlund
I added a helper method that reduces the amount of code to one line.
Henrik Söderlund
I +1 and marked as answered, but I still will have to use Refresh, since DataGrid column headers don't like binding and for some labels I use "Some String" + ":" and I don't know the way of concatenating strings when binding. Thanks for help though.
Artur
Ok, I will give you a few suggestions. For the datagrid column headers you could avoid setting the Header property directly and instead use a TextBlock or a ContentControl which you bind to your ResourceWrapper. As for the formatting you can work around it by using a value converter on your binding. Tim Heuer has an article on value converters here: http://tinyurl.com/5vcf3o
Henrik Söderlund