Question

I have a view model which has the name of an entry in my language resource file.
I tried to bind this value directly to the x:Uid attribute of the TextBlock in my XAML, but got a XAML error.

To get around this limitation I though about changing the property to return the value from the language file, but was concerned that doing so might not be a valid MVVM solution.
I also thought about creating a converter to set the text.

Way that does not work:

<StackPanel Orientation="Horizontal">
    <Image Margin="0,0,20,0" Source="{Binding IconPath}" />
    <TextBlock x:Uid="{Binding LanguageResourceName}" />
</StackPanel>

The view model I am binding to:

class Tab : ViewModelBase
{
    private string _IconPath,
        _LanguageResourceName;
    private ViewModelBase _ViewModel;

    /// <summary>
    /// The path to the icon to show on the tab.
    /// </summary>
    public string IconPath
    {
        get { return _IconPath; }
        set { SetProperty(ref _IconPath, value); }
    }

    /// <summary>
    /// The name of the entry in the language resource file to display on the tab.
    /// </summary>
    public string LanguageResourceName
    {
        get { return _LanguageResourceName; }
        set { SetProperty(ref _LanguageResourceName, value); }
    }

    /// <summary>
    /// The contents of the tab.
    /// </summary>
    public ViewModelBase ViewModel
    {
        get { return _ViewModel; }
        set { SetProperty(ref _ViewModel, value); }
    }
}

So what is the correct way to resolve this issue?

Was it helpful?

Solution

Converter is the best way to do it. Check out my answer here for a quick explanation. I've copied the Converter I define there below.

ResourceController is a simple Controller which gets a reference to a ResourceLoader and retrieves values via a method GetString(string resourceId).

public class ResourceTranslationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var valString = value as string;

        // If what is being converted is a string, return the resource translation
        // Else return something else, such as the object itself
        return valString == null ? value : ResourceController.GetString(valString);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Binding then works like:

<TextBlock Text="{Binding LanguageResourceName, Converter={StaticResource ResourceTranslationConverter}}" />

Make sure you've defined an accessible ResourceTranslationConverter. Possibly in the Page.Resources or even in your App.xaml (since you should only need one static reference).

Hope this helps and happy coding!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top