问题
How to make an array of dependency object properties bindable for later binding as a static resource?
The code I have now, it seems that my DependencyObject
bypasses the dependency property system...
I have the following class:
public class ValueMarker : DependencyObject
{
public static readonly DependencyProperty BrushProperty = DependencyProperty.Register("Brush", typeof(Brush), typeof(ValueMarker), new FrameworkPropertyMetadata(Brushes.Aqua));
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(ValueMarker), new FrameworkPropertyMetadata(0d));
public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register("Offset", typeof(double), typeof(ValueMarker), new FrameworkPropertyMetadata(0d));
public Brush Brush
{
get { return (Brush)GetValue(BrushProperty); }
set { SetValue(BrushProperty, value); }
}
public double Offset
{
get { return (double)GetValue(OffsetProperty); }
set { SetValue(OffsetProperty, value); }
}
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
}
In the XAML, I create a resource array of these with some bindings like so:
<x:Array Type="my:ValueMarker" x:Key="plainMarks">
<my:ValueMarker Brush="Red" Offset="-5" Value="{Binding Path=...}" />
<my:ValueMarker Brush="Orange" Offset="-5" Value="{Binding Path=...}"/>
<my:ValueMarker Brush="Orange" Offset="-5" Value="{Binding Path=...}"/>
<my:ValueMarker Brush="Red" Offset="-5" Value="{Binding Path=...}" />
</x:Array>
While debugging the bindings, I've noticed that should I remove the setter for the DP, the XAML would display an error saying the property is missing. It was my understanding that XAML uses DP system to assign value thus enabling binding. In this case, if the XAML expect a 'normal' property, binding is impossible. Anyone can enlighten me on how can I make it work?
回答1:
The reason you cannot bind your ValueMarkers here is because:
1.They are not in the VisualTree of your window/usercontrol.
2.They are not object of Type that can inherit DataContext even if they are not part of Visual Tree.
So in order to make your ValueMarkers bind to the properties in the View DataContext, first of all you will have to derive them from Freezable class like below:
public class ValueMarker : Freezable
{
//All your Dependency Properties comes here//
protected override Freezable CreateInstanceCore()
{
return new ValueMarker();
}
}
After doing this you can simply bind your object like below:
<my:ValueMarker x:Key="vm1" Brush="Orange" Offset="-5" Value="{Binding Path=Text1}"/>
Here Text1 is property in Windows/usercontrols DataContext
Then you can use this resource as:
<TextBox Text="{Binding Value, Source={StaticResource vm1}, StringFormat=F2}"/>
Similarly you can create resource for other ValueMarkers to use them in binding.
You will not be able to bind by creating the x:Array as simply x:Array not lies in visualtree and does not inherit DataContext hence its elements also have no access to it.
If you still want to use the collection whose element should support binding, then you will need to create your own collection class that should inherit Freezable and exposes DependancyProperty to capture the DataContext and set it on child elements also.
来源:https://stackoverflow.com/questions/19144410/make-dependency-object-properties-bindable-as-a-static-resource