Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TemplateBinding in Storyboard | ObjectAnimationUsingKeyFrames not working

I have the following setup. the problem is, that if I switch to the VisualState "Alarm", the AlarmBrush is not set. I have tried different "Bindings" (see below), but I only get errors like System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=AlarmBrush; DataItem=null; target element is 'DiscreteObjectKeyFrame' (HashCode=39320280); target property is 'Value' (type 'Object').

If I replace the value with an ResourceKey, then everything is fine. But I want to have this State dynamic, so a static resource is no opionion.

BaseClass

[TemplateVisualState(GroupName = "FooGroup", Name = "Alarm")]
public abstract class BaseClass : Control
{
    public static readonly DependencyProperty AlarmBrushProperty = DependencyProperty.Register("AlarmBrush", typeof(Brush), typeof(BaseClass), null);
    public Brush AlarmBrush
    {
        get { return (Brush)GetValue(AlarmBrushProperty); }
        set { SetValue(AlarmBrushProperty, value); }
    }
}

DerivedClass

public class DerivedClass : BaseClass
{
    public DerivedClass()
    {
        this.DefaultStyleKey = typeof(DerivedClass);
    }

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        VisualStateManager.GoToState(this, "Alarm", true);
    }
}

XAML Style

<Style TargetType="Basic:DerivedClass">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Basic:DerivedClass">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="FooGroup">
                            <VisualState x:Name="Alarm">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background)" Storyboard.TargetName="AlarmBorder">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding AlarmBrush, RelativeSource={RelativeSource TemplatedParent}}"/>
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Basic:DerivedClass}}, Path=AlarmBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="AlarmBorder" BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}"  BorderThickness="{TemplateBinding BorderThickness}">
                        <TextBlock Text="test" Foreground="{TemplateBinding Foreground}" TextWrapping="Wrap" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="BorderThickness" Value="5"/>
</Style>

xaml

<Foo:DerivedClass BorderBrush="#FFDA1F1F" AlarmBrush="#FF00FF0C"/>
like image 275
Dominic Jonas Avatar asked Dec 11 '25 02:12

Dominic Jonas


1 Answers

You are going to hate this but I remember this is one of the limitations in WPF. The Value property needs to be frozen which means you cannot use bindings to dynamically change it. Same thing goes to the To property of a ColorAnimation.

Since you are not actually animating the color (animating a Brush will simply change the color instantly), you can always obtain a reference of the AlarmBorder and manually set its Background.

like image 112
Justin XL Avatar answered Dec 13 '25 14:12

Justin XL



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!