I have the following class, which "hosts" a dependency property, that is registered for all types of FrameWorkElement.
Here it is:
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)
{
}
}
This example code DOES WORK:
<Border x:Name="_ErrorBorder" c:DPHost.MyString="ABC"/>
This example code DOES NOT WORK:
<ControlTemplate.Triggers>
<Trigger SourceName="_ImageCircle" Property="IsEnabled" Value="True">
<Setter TargetName="_ErrorBorder" Property="c:DPHost.MyString" Value="ABC"/>
</Trigger>
</ControlTemplate.Triggers>
The code does compile, the given trigger works 100% properly, but when I use the above setter code for "_ErrorBorder", I get the error:
"System.Windows.Markup.XamlParseException occurred"
InnerException: HResult=-2147467261 Message=The value can not be null Parametername: property ParamName=property Source=PresentationFramework StackTrace: bei System.Windows.Setter.CheckValidProperty(DependencyProperty property) bei System.Windows.Baml2006.WpfSharedBamlSchemaContext.<>c.b__341_0(Object target, Object value) bei System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value) bei MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value) bei MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value) InnerException:
I have tested to implement the "MyString" DP directly in a class of type Border, then it worked.
I think it is some kind of syntax error or a different behaviour of the DP system, when it comes to setters, where the DP is not directly hosted inside the user control.
Thank you for any hints or links or complete answers!
If you are curious what I want to achieve: I like to implement global and central DPs for all types of FrameWorkElement inside a UserControl library.
This is the answer/solution to this question: (big credit to ibebbs for taking the time to really help me)
Change the owner type from "FrameworkElement" to "DPHost" and let the class DPHost inherit from 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. Now this WORKS:
<Border x:Name="_ErrorBorder" c:DPHost.MyString="ABC"/>
2. Now this WORKS TOO (this was the error)
<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. Just a little explanation, what it is all about
I need different dependency properties for ALL types of FrameworkElement, without creating any new base classes. The goal is to implement a generic animation framework. So this "MyString" property was just an abstract example to help me, what I want to achieve.