WPF&x2013;转换器作为DependencyObject

WPF&x2013;转换器作为DependencyObject,wpf,binding,wpf-controls,converters,Wpf,Binding,Wpf Controls,Converters,无法将值绑定到Binding的ConverterParametr绑定只能在DependencyObject的dependencProperty上设置 我很想把IValueConverter转换器实现为DependencyObject public class AddConverter : DependencyObject, IValueConverter { public static readonly DependencyProperty AddIntegerProperty =

无法将值绑定到
Binding
ConverterParametr
<代码>绑定只能在
DependencyObject
dependencProperty
上设置

我很想把
IValueConverter
转换器实现为
DependencyObject

public class AddConverter : DependencyObject, IValueConverter
{
    public static readonly DependencyProperty AddIntegerProperty =
        DependencyProperty.Register(nameof(AddInteger),
            typeof(int),
            typeof(AddConverter),
            new PropertyMetadata(0));

    public int AddInteger
    {
        get => (int)GetValue(AddIntegerProperty);
        set => SetValue(AddIntegerProperty, value);
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is int intValue)) return 0;
        return intValue + AddInteger;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int intValue;
        try
        {
            intValue = System.Convert.ToInt32(value);
        }
        catch (Exception)
        {
            return 0;
        }

        return intValue - AddInteger;
    }
}
让我们在示例视图中查看它

<TextBox>
    <TextBox.Text>
        <Binding Path="MyIntegerProperty">
            <Binding.Converter>
                <local:AddConverter AddInteger="{Binding MyAddIntegerProperty, Mode=OneWay}" />
            </Binding.Converter>
        </Binding>
    </TextBox.Text>
</TextBox>

结果是
AddInteger
仍然返回默认值。通过提供的
绑定
,没有更改
AddInteger
依赖项属性的原因是什么



脚注:
MultiBinding
对我没有帮助,因为
ConvertBack
方法仅由控件提供的值组成。这个问题也应该在ViewModel中解决,但我对使用转换器的解决方案感到好奇。

问题是,首先,转换器无法继承其所在的DataContext,因此绑定无法工作:如果您对已有的绑定进行跟踪,您将在VS输出中看到“未找到Framework mentor”(见附录a)。这也是为什么您不能仅仅从FrameworkElement派生并使用
RelativeSource={RelativeSource AncestorType=Whatever}
:您已经脱离了可视化树。没有祖先。此外,即使有框架指导者,DependencyObject也不能为绑定提供源。消息来源必须明确。只有从FrameworkElement继承的类才能继承DataContext

所以我偷了一个BindingProxy类()并用它来提供绑定的源代码。这有点笨拙,但我想到的另一种选择是从Freezable继承转换器,本质上赋予它BindingProxy的属性,并在参考资料中创建转换器。它起作用了,但我更喜欢它的组织方式

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    #region Data Property
    public Object Data
    {
        get { return (Object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register(nameof(Data), typeof(Object), typeof(BindingProxy),
            new PropertyMetadata(null));
    #endregion Data Property
}
XAML

System.Windows.Data警告:56:为绑定(哈希=21653700)创建了BindingExpression(哈希=14964341)
System.Windows.Data警告:58:路径:“MyAddIntegerProperty”
System.Windows.Data警告:60:BindingExpression(哈希=14964341):默认模式解析为单向
System.Windows.Data警告:61:BindingExpression(哈希=14964341):默认更新触发器已解析为PropertyChanged
System.Windows.Data警告:62:BindingExpression(哈希值=14964341):附加到WpfApp2.AddConverter2.AddInteger(哈希值=57434139)
System.Windows.Data警告:64:BindingExpression(哈希=14964341):使用Framework mentor
System.Windows.Data警告:67:BindingExpression(哈希=14964341):解析源
System.Windows.Data警告:69:BindingExpression(哈希=14964341):找不到Framework mentor
System.Windows.Data警告:65:BindingExpression(哈希=14964341):解析源延迟
System.Windows.Data警告:67:BindingExpression(哈希=14964341):解析源
System.Windows.Data警告:69:BindingExpression(哈希=14964341):找不到Framework mentor

由于转换器不是
框架元素
,因此通过
相对资源查找工具查找
数据上下文
也没有帮助。我懂了。谢谢你的例子。@David正确。此外,即使您继承了FrameworkElement,FindAncestor也不会工作,因为您已经脱离了可视化树——再也没有框架导师了。
<StackPanel.Resources>
    <local:BindingProxy
        x:Key="VMProxy"
        Data="{Binding}"
        />
</StackPanel.Resources>
<TextBlock>
    <TextBlock.Text>
        <Binding Path="MyIntegerProperty">
            <Binding.Converter>
                <local:AddConverter
                    AddInteger="{Binding Data.MyAddIntegerProperty, Source={StaticResource VMProxy}}" 
                    />
            </Binding.Converter>
        </Binding>
    </TextBlock.Text>
</TextBlock>
AddInteger="{Binding MyAddIntegerProperty, Mode=OneWay, 
    PresentationTraceSources.TraceLevel=High}"
System.Windows.Data Warning: 56 : Created BindingExpression (hash=14964341) for Binding (hash=21653700)
System.Windows.Data Warning: 58 :   Path: 'MyAddIntegerProperty'
System.Windows.Data Warning: 60 : BindingExpression (hash=14964341): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=14964341): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=14964341): Attach to WpfApp2.AddConverter2.AddInteger (hash=57434139)
System.Windows.Data Warning: 64 : BindingExpression (hash=14964341): Use Framework mentor <null>
System.Windows.Data Warning: 67 : BindingExpression (hash=14964341): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14964341): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=14964341): Resolve source deferred
System.Windows.Data Warning: 67 : BindingExpression (hash=14964341): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14964341): Framework mentor not found