在控件模板中设置 "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 有更多信息。
我有以下 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 有更多信息。