在控件模板中设置 "hosted" 依赖项 属性 不起作用

Setting "hosted" dependency property in control template does not work

我有以下 class,其中 "hosts" 一个依赖项 属性,已为所有类型的 FrameWorkElement 注册。

这里是:

public class DPHost: DependencyObject
    {
        public static readonly DependencyProperty MyStringProperty = DependencyProperty.Register("MyString", typeof(String), typeof(FrameworkElement), new PropertyMetadata(OnMyStringChanged));

        public static String GetMyString(DependencyObject obj)
        {
            return (String)obj.GetValue(MyStringProperty);
        }

        public static void SetMyString(DependencyObject obj, String value)
        {
            obj.SetValue(MyStringProperty, value);
        }

        public String MyString
        {
            get { return (String)GetValue(MyStringProperty); }
            set { SetValue(MyStringProperty, value); }
        }


        private static void OnMyStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }
    }

此示例代码 有效:

    <Border x:Name="_ErrorBorder" c:DPHost.MyString="ABC"/>

此示例代码工作:

<ControlTemplate.Triggers>
    <Trigger SourceName="_ImageCircle" Property="IsEnabled" Value="True">
        <Setter TargetName="_ErrorBorder" Property="c:DPHost.MyString" Value="ABC"/>
    </Trigger>
</ControlTemplate.Triggers>

代码确实可以编译,给定的触发器 100% 正常工作,但是当我对“_ErrorBorder”使用上面的 setter 代码时,我得到错误:

"System.Windows.Markup.XamlParseException occurred"

内部异常: HResult=-2147467261 Message=值不能为空 参数名称:属性 参数名=属性 源=PresentationFramework 堆栈跟踪: bei System.Windows.Setter.CheckValidProperty(DependencyProperty 属性) bei System.Windows.Baml2006.WpfSharedBamlSchemaContext.<>c.b__341_0(对象目标,对象值) bei System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(对象实例,对象值) bei MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember 成员, 对象 obj, 对象值) bei MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(对象实例,XamlMember 属性,对象值) 内部异常:

我测试过直接在 class 类型的 Border 中实现 "MyString" DP,然后成功了。

我认为这是某种语法错误或 DP 系统的不同行为,当涉及到 setters 时,DP 不直接托管在用户控件中。

感谢您提供任何提示或链接或完整的答案!

如果您对我想要实现的目标感到好奇:我喜欢在 UserControl 库中为所有类型的 FrameWorkElement 实现全局和中央 DP。




这是这个问题的 answer/solution:(非常感谢 ibebbs 花时间真正帮助我)

将所有者类型从 "FrameworkElement" 更改为 "DPHost" 并让 class DPHost 从 FrameworkElement 继承。

public class DPHost:FrameworkElement
    {

        public static readonly DependencyProperty MyStringProperty = DependencyProperty.RegisterAttached("MyString", typeof(String), typeof(DPHost), new PropertyMetadata(OnMyStringChanged));


        public static String GetMyString(DependencyObject obj)
        {
            return (String)obj.GetValue(MyStringProperty);
        }

        public static void SetMyString(DependencyObject obj, String value)
        {
            obj.SetValue(MyStringProperty, value);
        }

        private static void OnMyStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }
    }

1.现在这个工作:

<Border x:Name="_ErrorBorder"  c:DPHost.MyString="ABC"/>

2。现在这也行得通(这是错误)

 <ControlTemplate.Triggers>
     <Trigger SourceName="_ImageCircle" Property="IsEnabled" Value="True">
        <Setter TargetName="_ErrorBorder"   Property="c:DPHost.MyString" Value="THE BORDER" />
        <Setter TargetName="_ImageCircle"   Property="c:DPHost.MyString" Value="THE CIRCLE"/>
     </Trigger>
  </ControlTemplate.Triggers>

3。稍微解释一下,这是怎么回事

我需要 ALL 类型的 FrameworkElement 的不同依赖属性,而无需创建任何新的基础 classes。目标是实现一个通用的动画框架。所以这个 "MyString" 属性 只是一个抽象的例子来帮助我实现我想要实现的目标。

Michael,查看代码,看起来您实际上是在尝试定义 'attached property' 而不是常规依赖项 属性。我不是 100% 相信这会解决 trigger/setter 问题,但试试也无妨。

另请注意,您的代码中依赖项 属性 的 'owner' 是 'FrameworkElement',而它应该是 'DPHost'。 This answer 有更多信息。