How do I change the CultureInfo of a converter?

I have a UserControl that displays some DP text from a UserControl. For this, a converter is used. I understand that the culture parameter is the "en-US" culture unless you specify a different culture in the ConverterCulture value of the binding or in the xml: lang attribute.

But how can I change the culture from outside the UserControl?

This is my UserControl:

<UserControl x:Class="CultInfoConverter.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:CultInfoConverter"
    DataContext="{Binding RelativeSource={RelativeSource Self}}" 
    Tag="{x:Null}">
    <UserControl.Resources>
        <my:MyConverter x:Key="MyConverter" />
    </UserControl.Resources>
    <StackPanel Orientation="Horizontal" >
        <TextBlock Margin="8">My converter culture is</TextBlock>
        <TextBlock FontWeight="Bold" Text="{Binding Tag, Converter={StaticResource MyConverter}}" />
    </StackPanel>
</UserControl>

      

For demonstration purposes, the converter simply returns the name of the culture information passed to it:

public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return culture.Name;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

      

In my window, I have two instances of the custom control, and each one should display a different culture. But both just show the "en-US" standard.

<Window x:Class="CultInfoConverter.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    xmlns:my="clr-namespace:CultInfoConverter">
    <StackPanel>
        <TextBlock Margin="8">using xml:lang="de-DE"</TextBlock>
        <my:MyUserControl xml:lang="de-DE"/>
        <TextBlock Margin="8">using xml:lang="fr-FR"</TextBlock>
        <my:MyUserControl xml:lang="fr-FR"/>
    </StackPanel>
</Window>

      

+1


a source to share


2 answers


The reason why your example doesn't work is because you are setting the xml: lang property after the MyUserObject has already been created. The TextBlock (both the Binding and the converter) has already been created using the default language, which is en-US.

TheDuke is wrong regarding multiple xml: lang attributes. While it is true you only have 1 UI thread and it only has 1 culture, each FrameworkElements are allowed to have their own xml: lang . To test this, set your xml: lang attribute to MyAserControl XAML (in your first codelist) in de-DE. You should see that de-DE is now bold twice.

To solve this problem, you need to configure the DataBinding AFTER MyUserControl and the Language / xml: lang attribute has been set. I did a quick test by adding a DataBinding event to the MyUserControl Loaded event. This gives you the results I think you expect (de-DE on the first line, fr-Fr on the second).

alt text http://img35.imageshack.us/img35/4588/howtochangetheculturein.png

MyControl XAML List:



<UserControl
    x:Class="WPFCultureTester.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFCultureTester"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Tag="{x:Null}"
    Loaded="UserControl_Loaded">
    <StackPanel Orientation="Horizontal" >
        <TextBlock Margin="8">My converter culture is</TextBlock>
        <TextBlock x:Name="foo" FontWeight="Bold" />
    </StackPanel>
</UserControl>

      

MyControl Code-Behind:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace WPFCultureTester
{
    /// <summary>
    /// Interaction logic for MyUserControl.xaml
    /// </summary>
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.foo.SetBinding(
                TextBlock.TextProperty,
                new Binding("") { Converter = CultInfoConverter.Converter });
        }
    }
}

      

By the way, I allowed to add the Singleton Converter to the CultInfoConverter and rename some namespaces, so you might have to change it if you are doing direct cut / paste.

+3


a source


I am not an expert on globalization, in fact I don't think I have ever tried it, but hope this helps.

Here's my UserControl.xaml

<UserControl x:Class="Tab_Question.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="30">
<Grid>
    <TextBlock Text="{Binding Path=CultureName, FallbackValue=bindingError}" />
</Grid>

      

Here is the code behind UserControl.cs

    public partial class UserControl1 : UserControl
{
    public static DependencyProperty CultureStringProperty =
        DependencyProperty.RegisterAttached("Culture", typeof(String), typeof(UserControl1));

    public static DependencyProperty CultureNameProperty =
        DependencyProperty.Register("CultureName", typeof(String), typeof(UserControl1));

    public String CultureString
    {
        get
        {
            return (String)GetValue(UserControl1.CultureStringProperty);
        }
        set
        {
            if (CultureString != value)
            {
                SetValue(UserControl1.CultureStringProperty, value);
                DoSomethingWithCulture();
            }
        }
    }

    private void DoSomethingWithCulture()
    {
        // Good to continue
        CultureInfo newCulture = CultureInfo.GetCultureInfo(CultureString);
        SetValue(UserControl1.CultureNameProperty, newCulture.Name);
    }

    public UserControl1()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

      

Finally, heres the Window.xaml



<Window
x:Class="Tab_Question.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Tab_Question"
Title="Window1" Height="300" Width="300">
<StackPanel>
    <local:UserControl1 CultureString="en-us" />
    <local:UserControl1 CultureString="en-gb" />
</StackPanel>

      

I'll try to explain what I did, I hope he answers the question.

I have set up a connected DependencyProperty on UserControl that allows the CultureInfo String to be passed to the UserControl when the String is updated. The UserControl creates a CultureInfo object that you can store in a member variable and updates the CultureName DependancyProperty that the TextBlock on the UserControl binds to.

I'm not sure why setting the XmlLang attribute you tried isn't working, but suspect it has something to do with the UI thread being able to only have one language.

I know this does not match the sample code you provided, but I hope it provides you with a starting point to change and adapt.

Ben

0


a source







All Articles