codingseb / Localization

A suite to localize C# and WPF projects easily based on file format you choose.
MIT License
37 stars 6 forks source link

Use TrTextIdConverter in ControlTemplate not working #1

Closed linhmc closed 3 years ago

linhmc commented 3 years ago

Dear Coding Seb, Thank for useful project. I have an issue please help. Language not change when select change in language combobox

<ControlTemplate TargetType="ListBoxItem">
    <Grid>
        <Grid x:Name="GridLevel0">
            <TextBlock Text="{Binding ContentName, Converter={TrTextIdConverter DefaultText='DefaultText'}, UpdateSourceTrigger=PropertyChanged}"/>
        </Grid>
    </Grid>
</ControlTemplate>

image

codingseb commented 3 years ago

Hello @linhmc . Where did you put your ControlTemplate ? I tried in a `ListBox.Resources' but VisualStudio do not like it without a Key and with a key it can not be applied.

Personally, I usually prefer to define a DataTemplate in ListBox.ItemTemplate or a DataTemplateSelector in ListBox.ItemTemplateSelector to customize the way ListBoxItems are shown.

Something like that :

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ListBoxItem">
            <Grid>
                <Grid x:Name="GridLevel0">
                    <TextBlock Text="{Binding ContentName, Converter={TrTextIdConverter DefaultText='DefaultText'}, UpdateSourceTrigger=PropertyChanged}"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
public class ItemViewModel
{
    public string ContentName { get; set; }
    public int OtherValue { get; set; }
}
public class MainViewModel
{
    // ...

    public ObservableCollection<ItemViewModel> Items { get; set; } = new ObservableCollection<ItemViewModel>()
    {
        new ItemViewModel()
        {
            ContentName="TextId1",
            OtherValue = 1
        },
        new ItemViewModel()
        {
            ContentName="TextId2",
            OtherValue=2
        }
    };

    // ...
}

This kind of stuff work for me.

codingseb commented 3 years ago

In fact, in templates, converters are not sensitive to language change. This is due to the way bindings works in templates. This is why I addded the possibility to specify TextId as a Binding in Tr Markup in last version of CodingSeb.Localization.WPF.

So you can do this :

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ItemViewModel">
            <Grid>
                <Grid x:Name="GridLevel0">
                    <TextBlock Text="{Tr {Binding ContentName}, DefaultText='DefaultText'}"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<DataTemplate DataType="ListBoxItem">
<!-- or  -->
<DataTemplate DataType="ItemViewModel">
<!-- Both work for me (Depending if you prefer to Template the UI ListBoxItem or the corresponding ViewModel type) -->
linhmc commented 3 years ago

Hello @linhmc . Where did you put your ControlTemplate ? I tried in a `ListBox.Resources' but VisualStudio do not like it without a Key and with a key it can not be applied.

Personally, I usually prefer to define a DataTemplate in ListBox.ItemTemplate or a DataTemplateSelector in ListBox.ItemTemplateSelector to customize the way ListBoxItems are shown.

Something like that :

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ListBoxItem">
            <Grid>
                <Grid x:Name="GridLevel0">
                    <TextBlock Text="{Binding ContentName, Converter={TrTextIdConverter DefaultText='DefaultText'}, UpdateSourceTrigger=PropertyChanged}"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
public class ItemViewModel
{
    public string ContentName { get; set; }
    public int OtherValue { get; set; }
}
public class MainViewModel
{
    // ...

    public ObservableCollection<ItemViewModel> Items { get; set; } = new ObservableCollection<ItemViewModel>()
    {
        new ItemViewModel()
        {
            ContentName="TextId1",
            OtherValue = 1
        },
        new ItemViewModel()
        {
            ContentName="TextId2",
            OtherValue=2
        }
    };

    // ...
}

This kind of stuff work for me.

Hi @codingseb Thank you for reply. I put code in like this: image

I'll try it your way. Thank you so much.

linhmc commented 3 years ago

In fact, in templates, converters are not sensitive to language change. This is due to the way bindings works in templates. This is why I addded the possibility to specify TextId as a Binding in Tr Markup in last version of CodingSeb.Localization.WPF.

So you can do this :

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ItemViewModel">
            <Grid>
                <Grid x:Name="GridLevel0">
                    <TextBlock Text="{Tr {Binding ContentName}, DefaultText='DefaultText'}"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<DataTemplate DataType="ListBoxItem">
<!-- or  -->
<DataTemplate DataType="ItemViewModel">
<!-- Both work for me (Depending if you prefer to Template the UI ListBoxItem or the corresponding ViewModel type) -->

Actually I am using TranslateMe version, don't know if it helps

codingseb commented 3 years ago

Actually I am using TranslateMe version, don't know if it helps

OK, No it's not supported in TranslateMe I am sorry. Take note that TranslateMe archived and is now obsolete. It will not get further updates. The CodingSeb.Localization suite is the new way to go. Normally, the change of library should only take a few changes.

linhmc commented 3 years ago

Hello @linhmc . Where did you put your ControlTemplate ? I tried in a ListBox.Resources' but VisualStudio do not like it without a Key and with a key it can not be applied. Personally, I usually prefer to define aDataTemplateinListBox.ItemTemplateor aDataTemplateSelectorinListBox.ItemTemplateSelector` to customize the way ListBoxItems are shown. Something like that :

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="ListBoxItem">
            <Grid>
                <Grid x:Name="GridLevel0">
                    <TextBlock Text="{Binding ContentName, Converter={TrTextIdConverter DefaultText='DefaultText'}, UpdateSourceTrigger=PropertyChanged}"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
public class ItemViewModel
{
    public string ContentName { get; set; }
    public int OtherValue { get; set; }
}
public class MainViewModel
{
    // ...

    public ObservableCollection<ItemViewModel> Items { get; set; } = new ObservableCollection<ItemViewModel>()
    {
        new ItemViewModel()
        {
            ContentName="TextId1",
            OtherValue = 1
        },
        new ItemViewModel()
        {
            ContentName="TextId2",
            OtherValue=2
        }
    };

    // ...
}

This kind of stuff work for me.

Hi @codingseb Thank you for reply. I put code in like this: image

I'll try it your way. Thank you so much.

Hi @codingseb I tried your suggest: image but It is not work. Language not change when I selection changed other language. image

codingseb commented 3 years ago

Hi @codingseb I tried your suggest: image but It is not work. Language not change when I selection changed other language. image

Yes because converters can not update a binding in a template. Because of the way WPF works with templates the converter can not get the DependencyObject and the DependencyProperty on which the binding is set and so can not update the value when language change in the case of a template. So the only way to make language change effective in a template is with the Tr' Markup with TextId as Binding ofLocalization.WPF` that create internally a MultiBinding.

<TextBlock Text="{Tr {Binding ContentName}, DefaultText='DefaultText'}"/>

As I said TranslateMe lib is obsolete for at least a year now and will not get updates (bug corrections, new functionnalities...).

If you want to keep TranslateMe. Feel free to adapt your own Tr Markup from Here (it's MIT licenced) or eventually to make your own MultiBinding->IMultiValueConverter to make it work.