Colin Dawson
Colin Dawson

Reputation: 465

Binding for Localization

I'm working on a solution to a localization problem. This isn't the normal language localisation.

<Label Content="{Binding myDictionary[A Test], FallbackValue=A Test}"/>

In practice the above code calls into the Dictionary in the view model, which is declared as

public Dictionary<string, string> myDictionary

The problem is that I have to define the string "A Test" twice in the label. once as in the index in the binding, and again in the FallbackValue.

What I would like to end up with is something that looks like this...

<Label Content="{Binding myDictionary[A Test]}"/>

At the moment what happens when I do this is that the Xaml designer in Visual studio can't resolve myDictionary (as it won't know the datacontext so can't hook up to the viewmodel where it's defined) this means that the label will display as blank, which won't will make visual design harder.

I've looked into calling a static method however for myDictionary to function properly, it needs to be instantiated in the view model.

Is there a way of having either the index value "A Test" show up in the designer without having to use a fallback value?

The goal is to be able to have the content refreshed if the value in myDictionary[A Test] is updated (In reality myDictionary is observable)

Upvotes: 3

Views: 869

Answers (2)

Mark Feldman
Mark Feldman

Reputation: 16138

Best way to handle this IMO is with a custom markup extension placed within a custom namespace, it allows you to write XAML like this:

<TextBlock Text="{Translate 'Hello World!'} />

What the Translate extension class returns is entirely up to you, typically you have it do a look-up into a Dictionary using the provided string as the index and, if it doesn't find it, just returns the string itself.

One of the nice things about this particular implementation is that it adds a listener to the Translation manager for every binding that is made, so they all automatically update at run-time whenever the current language is changed.

The one thing you do have to keep in mind though is to place the Translate extension class itself within its own project. Not sure why, it seems to be a bug in VS, but XAML files don't seem to be able to use custom markup extensions declared in the same project.

Upvotes: 1

ΩmegaMan
ΩmegaMan

Reputation: 31721

as it won't know the datacontext so can't hook up to the viewmodel where it's defined

Not so.... One can use a design time only context by specifying it in the page's meta data atttributes such as:

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance {x:Type viewModels:MainVM}}"

by doing that you can setup a design time only dictionary to use.


Read about here in MSDN magazine:

MVVM - Maximizing the Visual Designer’s Usage with Design-Time Data

Note one can still use the Blend namespaces in non Blend editors such as Visual Studio. Otherwise don't be afraid to use/learn Blend as needed.


If from your actual VM with real data, in design mode its good to ignore certain objects/actions which may cause issues. Here is a check to determine if the action is in design mode, if it is not then it executes the block, otherwise it is ignored because it is in design mode.

if (!DesignerProperties.GetIsInDesignMode(this))

Upvotes: 1

Related Questions