I want template control that dynamically generates different shapes according to a dependency property.The control looks like this:
<Style TargetType="local:ColorShape">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ColorShape">
<ContentControl x:Name="shapeParent">
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It has a depdency property for the shape: public ShapeType
ShapeType
{
get { return (ShapeType)GetValue(ShapeTypeProperty); }
set { SetValue(ShapeTypeProperty, value); }
}
public static readonly DependencyProperty ShapeTypeProperty =
DependencyProperty.Register("ShapeType", typeof(ShapeType), typeof(ColorShape), new PropertyMetadata(ShapeType.Circle));
I generate the shape in the OnApplyTemplate
method:
protected override void OnApplyTemplate()
{
var shapeParent = (ContentControl)this.GetTemplateChild("shapeParent");
var shape = GetShape(ShapeType);
shapeParent.Content = shape;
base.OnApplyTemplate();
}
I can DataBind the property, and it works the first time I create the control:
<Controls:ColorShape Grid.Row="1" Width="200" Height="200" Stroke="Black" ShapeType="{x:Bind ViewModel.Shape, Mode=OneWay}" StrokeThickness="5" Fill="{x:Bind ViewModel.Color, Mode=OneWay}" />
But if I modify the bound property in the ViewModel, that generates an INotifyPropertyChange
notification but doesn't repaints the template control
I tried to add a callback in the dependency property of the template control, and I can see it refreshes the dependency property with the new values bound to the property (in this case ViewModel.Shape
), but it doesn't refresh the UI (never calls again OnApplyTemplate
). I tried to manually call ApplyTemplate
method, and the event OnApplyTemplate
doesn't get fired ever.
OnApplyTemplate
is only called once, when the template is generated. It will only be called again, when you change the Template on the control.
What you need is a PropertyChangedCallback
on the DependencyProperty:
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0, OnPropertyChanged);
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Do what you need here
}
(The part you were missing is the second parameter at new PropertyMetadata(...)
.