【问题标题】:WPF Attached Property Data BindingWPF 附加属性数据绑定
【发布时间】:2023-09-15 02:56:01
【问题描述】:

我尝试使用带有附加属性的绑定。但不能让它工作。

public class Attached
{
    public static DependencyProperty TestProperty =
        DependencyProperty.RegisterAttached("TestProperty", typeof(bool), typeof(Attached),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Inherits));

    public static bool GetTest(DependencyObject obj)
    {
        return (bool)obj.GetValue(TestProperty);
    }

    public static void SetTest(DependencyObject obj, bool value)
    {
        obj.SetValue(TestProperty, value);
    }
}

XAML 代码:

<Window ...>
    <StackPanel local:Attached.Test="true" x:Name="f">
        <CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}" />
        <CheckBox local:Attached.Test="true" IsChecked="{Binding (local:Attached.Test), Mode=TwoWay}" />
    </StackPanel>
</Window>

还有绑定错误:

System.Windows.Data Error: 40 : BindingExpression path error: '(local:Attached.Test)' property not found on 'object' ''StackPanel' (Name='f')'. BindingExpression:Path=(local:Attached.Test); DataItem='StackPanel' (Name='f'); target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')

【问题讨论】:

    标签: wpf xaml binding attached-properties


    【解决方案1】:

    信不信由你,只需添加Path= 并在绑定到附加属性时使用括号:

    IsChecked="{Binding Path=(local:Attached.Test), Mode=TwoWay, RelativeSource={RelativeSource Self}}"
    

    此外,您对RegisterAttached 的调用应传入“Test”作为属性名称,而不是“TestProperty”。

    【讨论】:

    • 我已经尝试过了,但遇到了一个例外:Der Eigenschaftspfad ist ungültig。 \"附加\" besitzt keine öffentliche Eigenschaft mit dem Namen \"Test\"。 --> Engl: 属性路径无效。 “附加”不拥有公共财产“测试”
    • RegisterAttached 调用应该通过“Test”,而不是“TestProperty”作为属性名称。
    • 我希望我能多次投票。确保在进行此更改后重建项目。我第一次忘了做,还以为 Path= 没用。
    • 为什么需要括号?应该阅读什么参考资料才能了解这些神秘的东西?
    • 括号只是附加属性系统中的“索引器”。这是 WPF 区分附加属性和直接属性的方式。我想编译器会很困惑,无法尝试找出哪些属性是附加的,哪些不是,所以使用括号提供了这个提示。如果您好奇,实际上,WPF 会为附加属性创建一个 PropertyPath,如下所示:new PropertyPath("(0)", new object[] { propertyName }),假设 propertyNameString
    【解决方案2】:

    我更愿意将此作为对 Kent 回答的评论发布,但由于我没有足够的代表这样做......只是想指出从 WPF 4.5 开始,添加 Path= 不是不再需要了。但是附加的属性名称仍然需要用括号括起来。

    【讨论】:

    • 我自己只是想发表评论,没想到这是 WPF 4.5 及更高版本的功能...很高兴知道,谢谢!
    • 不知道为什么,但是如果我不添加 Path= 并且我正在运行 WPF 4.5 我正在运行 Win 8.1,WPF 会崩溃
    • 老兄,你真的拯救了我的一天。非常感谢。我使用 .net 4.0 并且没有 Path=(...) 它根本不起作用。
    • .NET 4.8.2 here - 由于某些奇怪的原因,在某些嵌套自定义控件中绑定到附加属性在 某些 情况下有效,但并非总是如此。添加Path= 只是解决了我在 10 小时内无法解决的问题。来自PresentationTraceSources 之类的...property not found... 的消息也不见了。血腥的 WPF 魔法。每当绑定到控件模板中的附加属性时,我都会使用Path=。也许是因为没有 Path,Binding 在绑定构造函数中而不是在 Path 属性设置器中设置 Path 槽?
    【解决方案3】:

    放置一个括号有效。我必须将父 contentcontrol 自动绑定到 datatemplate 中的 textblock。自动化 ID 是一个附加属性。

    我将属性放在括号中并且绑定有效。

    AutomationProperties.AutomationId="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContentControl},Path=(AutomationProperties.AutomationId)}" 
    

    【讨论】: