XAMLMarkupExtensions/WPFLocalizeExtension

Bindings in LocTextExtension

Closed this issue · 6 comments

Connected with PR #241

First of all, thanks for this change. In most places code has become more readable. Only in two places we have problem with in order to completely refuse LocProxy. Also have two addition samples which can be interested.

Sample 1
We have own AvailabilityToMessageKeysConverter, which inherit IMultiValueConverter. It returns different keys depending on the Bindings. lex:Loc support binding only at constructor and it's impossible to easy use multibinding. Is it possible to create new parameter in LocExtension named KeyBinding and use it for all types of bindings?

<lex:LocProxy x:Name="MessageProxy">
    <lex:LocProxy.Source>
        <MultiBinding Converter="{AvailabilityToMessageKeysConverter}">
            <Binding Path="PaymentTypesAvailability" />
            <Binding Path="PaymentTypeLimit" />
        </MultiBinding>
    </lex:LocProxy.Source>
</lex:LocProxy>

<TextBlock Text="{Binding ElementName=MessageProxy, Path=Result}" />

Sample 2
We have strings like: 'The price is {0} rubles'. Also we have our own FormatStringConverter which has first parameter as formatString and others as parameters. LocTextExtension support only FormatSegment as strings and doesn't support as Binding. is it possible to add support for parameters as bindings?

<lex:LocProxy x:Name="LocProxy"
              Source="{x:Static l:LocalizationKeys.Payment_Price}" />
<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{c:FormatStringConverter}">
            <Binding ElementName="LocProxy" Path="Result" />
            <Binding Path="Amount" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Sample 3
LocTextExtension support only string key at constructor. We often use LocTextUpper and one day it will be usefull to use 'LocTextUpper' and Binding key.

Sample 4
Not supported {TemplateBinding MessageKey}. But it can easyly rewrote to {Binding RelativeSource={RelativeSource TemplatedParent}, Path=MessageKey}. If adding TemplateBinding is to complicated, then this problem can be ignored.

P.S.
First and second samples can be fixed with rewriting converters and passing <Binding Source="{x:Static lex:LocalizeDictionary.Instance}" Path="Culture"/> as culture change event. But I think it's not good idea: extra unobvious dependencies (which can be forgotten) and using singleton LocalizeDictionary.Instance in different places.

konne commented

@Karnah thanks for your great feedback.
Some first comments:

Sample 1

This is not my fault that Loc only support Binding at construtor. It is not possible to add KeyBinding because Loc is a MarkupExtension and not a Dependency Object.
I will dig into that If I see a better approach.

Sample 2

please see https://github.com/XAMLMarkupExtensions/WPFLocalizationExtension/blob/development/docs/GapText.md#gap-text

Sample 3

This Extensions gets deprecated, (LocText, LocUpper, LocLower,...) Please use Converter for UpperCase,...

Sample4

Please file an FeatureRequest just for TemplateBinding support for lex:Loc

PS

I know this is not the best possibility but I prefer that. WPF don't give a better to handle this issue.

konne commented

@Karnah

Sample 1

it should be possible that you do it with an static resource, the only disadvantage would be that you loose designe time translation support for that element. And I have to extend the the code for multibinding as a constructor. Please file an separate Feature Request for this, like TemplateBinding.
Because TemplateBinding have to be handle in a different approach.

This is not my fault that Loc only support Binding at construtor. It is not possible to add KeyBinding because Loc is a MarkupExtension and not a Dependency Object.
I will dig into that If I see a better approach.

There are idea about this. In xaml for MarkupExtension setters are call before ProvideValue. If restrict during runtime - it will work. I checked this sample and it work:

public class BindableLocExtension : LocExtension
{
    public Binding KeyBinding
    {
        get => (Binding) GetField("_binding").GetValue(this);
        set => GetField("_binding").SetValue(this, value);
    }

    private static FieldInfo GetField(string fileName)
    {
        return typeof(LocExtension)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
            .First(f => f.Name == fileName);
    }
}

If it is bad idea for you and doesn't exists some another options, I'll prefer if _binding became protected for use such realization in our code.

please see

Hmm. I can not use this with {x:Static ...}. There are any ways to pass x:Static to Path? Source property not working too.

Please file an FeatureRequest just for TemplateBinding support for lex:Loc

Should I just create separate issue about this? Or do you mean somthing else?

This Extensions gets deprecated, (LocText, LocUpper, LocLower,...) Please use Converter for UpperCase,...

This is really useful feature for us. Formatting using converter will require nesting or am I wrong?

konne commented

@Karnah
please make an PR with an example for BindableLocExtension I don't understand why this should work or how you would like to use it.

Please let us separate things so please follow up in different issues. So please add this issues

@konne
I created for sample 2 and sample 4 separate issues.
With sample 3 I understood - there is a Converter propery in LocExtension which can easily use.

konne commented

@Karnah
sample 3. I will add the converter in the next days.