I'm trying to create a MarkupExtension for WPF for use with translation. I have found some similar questions asked here including
MarkupExtension that uses a DataBinding value
How do I resolve the value of a databinding inside a MarkupExtension?
ultimately, this lead to the response by Torvin that looks really promising. However, just as a person in the comments, I have an issue where the value obtained by the target.GetValue()
is always returning null.
Here's some of the code.
Ultimately I have a set of static classes that contains a static KeyDefinition object that looks like the following
Public class KeyDefinition
{
Public string Key {get; set;}
Public string DefaultValue {get; set;}
}
The key ties back to a JSON resource while the DefaultValue is an English translation that we can use for Design Time display of the xaml.
Localization occurs through a static class like so Localize.GetResource(key)
My goal is to write XAML like this
<TextBlock Text="{Localize {Binding KeyDefinitionFromDataContext}}">
where KeyDefinitionFromDataContext
is a property in the view model that returns a reference to a KeyDefinition
object.
As per Torvin's response I created a MarkupExtension like so
public class LocalizeExtension : MarkupExtension
{
private readonly BindingBase _binding;
private static readonly DependencyProperty _valueProperty = DependencyProperty.RegisterAttached("Value", typeof(KeyDefinition), typeof(LocalizeExtension));
[ConstructorArgument("keyDefinition")
public KeyDefinition KeyDefinition {get; set;}
public LocalizeExtension(Binding binding)
{
_binding = binding;
}
public LocalizeExtension(KeyDefinition keyDefinition)
{
KeyDefinition = keyDefinition;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var pvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var target = pvt.TargetObject as DependencyObject;
var property = pvt.TargetProperty as DependencyProperty;
//If inside a template, WPF will call again when its applied
if (target == null)
return this;
BindingOperations.SetBinding(target, property, _binding);
KeyDefinition = (KeyDefinition)target.GetValue(_valueProperty);
BindingOperations.ClearBinding(target, property);
return Localize.GetResource(KeyDefinition.Key);
}
}
Now please forgive me, because I do not usually do WPF work, but this task has fallen to me. Whenever I run this code the value returned is always Null
. I've tried using strings directly instead of the 'KeyDefinition' object but run into the same problem.
I think what confuses me here is how the DependencyProperty on the target ever gets set because its private.
Any help is appreciated. Thanks!
_valueProperty
field in the SetBinding, GetValue, and ClearBinding calls, not the localproperty
variable (which is then useless). But even with that modification, the approach won't work. It looks like something that worked by accident, and that you should not be trying to do. Go with the other approach and attach a Binding Converter. – Cu