1

I'm using WPFLocalizationExtension for my WPF app. I have one ComboBox for languages selection. Item source is an ObservableCollection<KeyValuePair<string, string>> as below:

  • TITLE_LANGUAGE_ENGLISH : en
  • TITLE_LANGUAGE_VIETNAMESE: vi-VN

This is my xaml code:

<TextBlock Text="{lex:Loc TITLE_LANGUAGE}"></TextBlock>
<ComboBox Grid.Column="1" 
          ItemsSource="{Binding AvailableLanguages}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{lex:Loc Key={Binding Key}}"></TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

When I run the application, it throws me an exeption as below:

A 'Binding' cannot be set on the 'Key' property of type 'LocExtension'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject

How can I translate the ItemTemplate ?

Thank you,

Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
Redplane
  • 2,971
  • 4
  • 30
  • 59

2 Answers2

2

You could use an IMultiValueConverter together with a MultiBinding, so that you don't loose the ability to update the localization on-the-fly.

<ComboBox ItemsSource="{Binding AvailableLanguages}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding>
                        <MultiBinding.Bindings>
                            <Binding Path="Key" Mode="OneTime"/>
                            <Binding Path="Culture" Source="{x:Static lex:LocalizeDictionary.Instance}"/>
                        </MultiBinding.Bindings>
                        <MultiBinding.Converter>
                            <l:TranslateMultiConverter/>
                        </MultiBinding.Converter>
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

And here is the converter:

class TranslateMultiConverter : DependencyObject, IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length == 2)
        {
            var key = values[0] as string;
            if (key == null)
            {                
                return DependencyProperty.UnsetValue;
            }

            var cultureInfo = (values[1] as CultureInfo) ?? culture;

            return LocalizeDictionary.Instance.GetLocalizedObject(key, this, cultureInfo);
        }

        return values.FirstOrDefault();
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

The LocalizeDictionary will raise a PropertyChanged event when the app's language will change causing the MultiBinding to refresh the values.

Note that the converter is a DependencyObject too. This is to provide the context to the LocalizeDictionary when calling the GetLocalizedObject method.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • I believe your solution works because I succeeded with IValueConverter. Actually, the question can be closed , but one thing I wonder is whether any built in WPFLocalizationExtension converter or not. :) – Redplane Jul 10 '18 at 02:21
  • This is brilliant and the only working solution for localizing DataTemplates I found so far. – gartenriese Oct 03 '19 at 15:45
0

you have to bind to the Path Key directly. The TextBlock at DataTemplate points directly to a single KeyValuePair object, that you can access the property Key directly.

<TextBlock Text="{lex:Loc TITLE_LANGUAGE}"></TextBlock>
    <ComboBox Grid.Column="1" 
      ItemsSource="{Binding AvailableLanguages}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Key}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Update:

Maybe you have to add a Converter. Try WPFLocalizeExtension.TypeConverters.DefaultConverter or implement a class deriving from IValueConverter by yourself.

<ComboBox.Resources>
    <cv:DefaultConverter x:Key="DConv" />
</ComboBox.Resources>
<ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Key, Converter={StaticResource DConv}}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
WPFGermany
  • 1,639
  • 2
  • 12
  • 30
  • @Redplane: As I wrote, you could solve the last problem by writing your own Converter. My answer fixes the Binding error. You will not need a IMultiValueConverter, because you can get the static passed Culture in the Converter directly. – WPFGermany Jul 10 '18 at 06:51