Wobbles
Wobbles

Reputation: 3135

Using an IValueConverter on non bound data in XAML

I have an IValueConverter that I wrote to handle localization and translation in WPF elements;

public class LanguageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return string.Empty;

        if (value is string)
            return LocalizedStrings.Retreive((string)value);
        else
            return string.Empty;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

But I also want to use it in non bound data aswell, ie send a known string into the converter rather than a property from the elements data context. How can I go about that?

Guess I should clarify, my intent is to use this in XAML for the UI and would be helpful if it had a design time support aswell.

I did attempt a variation that used the ConverterParameter to feed the source string, but in design time all my text is replaced with System.Object text, so not very useful.

Would also like if at all possible to avoid creating a overloaded or inherited user-control.

Upvotes: 0

Views: 1030

Answers (2)

Grx70
Grx70

Reputation: 10349

You could create a MarkupExtension that would take a string as a parameter and call your converter in the ProvideValue override. Here's an example implementation:

public class TranslateExtension : MarkupExtension
{
    public TranslateExtension(string text)
    {
        Text = text;
    }

    private static readonly LanguageConverter _converter = new LanguageConverter();

    public string Text { get; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return _converter.Convert(Text, null, null, null);
    }
}

Then you'd use it in XAML like this:

<TextBlock Text="{local:Translate 'text to translate'}" />

Note though that changing language will require the XAML to be re-read as the ProvideValue method is only called once upon realization of your XAML definition. If you want a dynamic approach you could refer for example to this answer.

Upvotes: 4

mm8
mm8

Reputation: 169200

But I also want to use it in non bound data aswell, ie send a known string into the converter rather than a property from the elements data context. How can I go about that?

You can't really do this because the Convert method of a Converter will only be invoked when the binding to the source property is resolved and when the source property is updated. If the binding to the source property fails, for example when you have defined an invalid binding path in your XAML markup or when there simply is no DataContext to bind to, your Convert method won't be called.

And when there is no binding applied to the target property at all, the converter won't be invoked either.

So you will have to always make sure that there actually is a property to bind to for this to work. Maybe you can bind to a dummy property or something.

Upvotes: 0

Related Questions