如何解决MarkupExtension中数据绑定的值?

tox*_*erd 5 c# data-binding wpf markup-extensions

我已经为基于密钥的字符串翻译做了标记扩展.例

<TextBlock Text="{Translate myKey}" />
Run Code Online (Sandbox Code Playgroud)

现在我希望能够使用嵌套绑定来提供我的密钥.例:

<TextBlock Text="{Translate {Binding KeyFromDataContext}}" />
Run Code Online (Sandbox Code Playgroud)

当我这样做时,我得到一个System.Windows.Data.Binding对象.通过调用ProvideValue并传递ServiceProvider,我可以得到一个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;
Run Code Online (Sandbox Code Playgroud)

我可以得到这个bindingExpression,但DataItem属性为null.我已经像这样测试了我的绑定

<TextBlock Text="{Binding KeyFromDataContext}" />
Run Code Online (Sandbox Code Playgroud)

它工作正常.

有任何想法吗?

tor*_*vin 2

托克斯维尔的答案并不具有普遍性。如果原始绑定已经有转换器,它就会中断。或者当不可能编写转换器时。

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

有一个问题:当在模板内使用标记扩展时,没有目标元素(显然)。在这种情况下,您应该使用- 这样,应用模板时将再次调用扩展。return thisProvideValue()

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));
}
Run Code Online (Sandbox Code Playgroud)

  • 您能解释一下这里的附加属性是如何工作的吗?我总是从 `target.GetValue()` 得到 `null` ... (2认同)