如何解析MarkupExtension内部的数据绑定值? [英] How do I resolve the value of a databinding inside a MarkupExtension?

查看:69
本文介绍了如何解析MarkupExtension内部的数据绑定值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个标记扩展,用于根据键翻译字符串。示例

I've made a markup extension for translating strings based on a key. Example

<TextBlock Text="{Translate myKey}" />

现在,我希望能够使用嵌套绑定提供密钥。示例:

Now I want to be able to use nested bindings for providing my keys. Example:

<TextBlock Text="{Translate {Binding KeyFromDataContext}}" />

这样做时,我得到一个System.Windows.Data.Binding对象。通过调用ProvideValue并传递ServiceProvider可以得到BindingExpression:

When I do this I get a System.Windows.Data.Binding object. By calling ProvideValue and passing down the ServiceProvider I can get a BindingExpression:

var binding = Key as Binding;
if (binding == null) {
    return null;
}
var bindingExpression = binding.ProvideValue(_serviceProvider) as BindingExpression;
if (bindingExpression == null) {
    return null;
}
var bindingKey = bindingExpression.DataItem;

我可以获得此bindingExpression,但DataItem属性为null。我已经像这样测试了绑定

I can get this bindingExpression, but the DataItem property is null. I've tested my binding like this

<TextBlock Text="{Binding KeyFromDataContext}" />

,效果很好。

任何

推荐答案

toxvaerd的答案不是通用的。如果原始绑定已经具有转换器,则会中断。或者无法编写转换器。

The toxvaerd's answer is not universal. It breaks if the original binding already had a converter. Or when writing a converter is not possible.

有更好的解决方案。我们可以声明两个构造函数。使用绑定时,XAML将调用第二个接受 BindingBase 的对象。要解析绑定的值,我们可以声明一个私有的附加属性。为此,我们需要了解标记扩展的目标元素。

There's a better solution. We can declare two constructors. The second one accepting BindingBase will be called by XAML when a binding is used. To resolve the value of the binding, we can declare a private attached property. For this to work we need to know the target element of the markup extension.

有一个陷阱:当在模板内部使用标记扩展时,没有目标元素(很明显)。在这种情况下,您是中使用返回此来代替在自定义标记中的upmark-extensions-providevalue-method?forum = wpf rel = nofollow noreferrer> ProvideValue()-这样,在应用模板时将再次调用该扩展名。

There's a catch: when the markup extension is used inside a template, there is no target element (obviously). In this case you are supposed to use return this in ProvideValue() - this way the extension will be called again when the template is applied.

public class TranslateExtension : MarkupExtension
{
    private readonly BindingBase _binding;

    public TranslateExtension(BindingBase binding)
    {
        _binding = binding;
    }

    public TranslateExtension(string key)
    {
        Key = key;
    }

    [ConstructorArgument("key")]
    public string Key { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_binding != null)
        {
            var pvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
            var target = pvt.TargetObject as DependencyObject;

            // if we are inside a template, WPF will call us again when it is applied
            if (target == null)
                return this; 

            BindingOperations.SetBinding(target, ValueProperty, _binding);
            Key = (string)target.GetValue(ValueProperty);
            BindingOperations.ClearBinding(target, ValueProperty);
        }

        // now do the translation using Key
        return ...;
    }

    private static readonly DependencyProperty ValueProperty = 
        DependencyProperty.RegisterAttached("Value", typeof(string), typeof(TranslateExtension));
}

这篇关于如何解析MarkupExtension内部的数据绑定值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆