Silverlight TemplateBinding to RotateTransform
I am trying to create the simplest Silverlight templated control, and I can't seem to get TemplateBinding to work on the Angle property of a RotateTransform.
Here's the ControlTemplate from generic.xaml:
<ControlTemplate TargetType="local:CtlKnob">
<Grid x:Name="grid" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<RotateTransform Angle="{TemplateBinding Angle}"/> <!-- This does not work -->
<!-- <RotateTransform Angle="70"/> --> <!-- This works -->
</TransformGroup>
</Grid.RenderTransform>
<Ellipse Stroke="#FFB70404" StrokeThickness="19"/>
<Ellipse Stroke="White" StrokeThickness="2" Height="16" VerticalAlignment="Top"
HorizontalAlignment="Center" Width="16" Margin="0,2,0,0"/>
</Grid>
</ControlTemplate>
Here's the C#:
using System.Windows;
using System.Windows.Controls;
namespace CtlKnob
{
public class CtlKnob : Control
{
public CtlKnob()
{
this.DefaultStyleKey = typeof(CtlKnob);
}
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(CtlKnob), 开发者_Go百科null);
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty,value); }
}
}
}
Here is a workaround:
public class TemplatedControl1 : Control
{
public TemplatedControl1()
{
this.DefaultStyleKey = typeof(TemplatedControl1);
}
public override void OnApplyTemplate()
{
var transform = this.GetTemplateChild("Transform1") as RotateTransform;
transform.Angle = this.StartAngle;
base.OnApplyTemplate();
}
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(TemplatedControl1), null);
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
}
And the xaml:
<Style TargetType="local:TemplatedControl1">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TemplatedControl1">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Canvas>
<Polyline Fill="Black" >
<Polyline.RenderTransform>
<RotateTransform x:Name="Transform1" />
</Polyline.RenderTransform>
</Polyline>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Henrik has all ready provided the answer but I'll explain why its necessary.
Currently in Sliverlight 3 this sort of binding requires that object receiving the binding is a FrameworkElement
. Its the FrameworkElement
that has the SetBinding
method that allows this stuff to work.
RotateTransform
whilst being a DependencyObject
is not a FrameworkElement
and therefore cannot participate in this sort of binding. Silverlight 4 allows binding to work on DependencyObject
so theoritically this sort of code ought to work in SL4. I'll have to try that to see if that is true.
Thanks Anthony for explaining why it doesn't work.
Thanks Henrik for the workaround, it solves half of the problem: the Angle can now be set from Xaml. However, it still can't be set programmatically, but the missing bit is now easy.
Here's the full solution:
public class CtlKnob : Control
{
public CtlKnob()
{
this.DefaultStyleKey = typeof(CtlKnob);
}
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(CtlKnob),
new PropertyMetadata(AngleChanged));
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty,value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var transform = this.GetTemplateChild("RotateTransform") as RotateTransform;
transform.Angle = this.Angle;
}
private static void AngleChanged( DependencyObject dobj,
DependencyPropertyChangedEventArgs e )
{
var knob = dobj as CtlKnob;
var rotateTransform = knob.GetTemplateChild("RotateTransform") as
RotateTransform;
if (rotateTransform != null)
rotateTransform.Angle = (double)e.NewValue;
}
}
In Silverlight 3, you can only bind to FrameworkElements and not DependencyObjects. RotateTransform is not a FrameworkElement.
Silverlight 4 supports binding to DependencyObjects, so this works in Silverlight 4.
If you can upgrade to Silverlight 4, I'd consider it. Otherwise, a number of people have posted workarounds for Silverlight 3.
精彩评论