schulmaster schulmaster -4 years ago 92
C# Question

Storyboard Animates boarder but not background of same target

EDIT: For a clear example of what I'm going for visually, open up a Win 7 calculator, and click a key. It blooms up to orange, and back down to base on release.

I am trying to animate a WPF button, overlayed with a custom boarder, using a Story board and color animation. The custom button template works. The triggers work. I can even get the story board to work if I target a different property. The first code block is the style with a border brush animation, and it changes the button border successfully on press.

<Style x:Key="CustomButton" TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="Grid">
<Border x:Name="Border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
/>

<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="Red" >

</ColorAnimation>

</Storyboard>

</BeginStoryboard>

</Trigger.EnterActions>

</Trigger>


Next is the same template targeting the same button element, the boarder, but its background property, but this runs, but with no effect on press, hold or otherwise. WHY?

<Style x:Key="CustomButton" TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="Grid">
<Border x:Name="Border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
/>

<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" Storyboard.TargetName="Border" To="Red" >

</ColorAnimation>

</Storyboard>

</BeginStoryboard>

</Trigger.EnterActions>

</Trigger>



This isnt a dependency hierarchy issue as I can tell, since if i put a plain old setter in the trigger, targeting Border by name, and its Background property, the background dies indeed change on press. For this reason, i I don't think an event trigger is necessary because other changes trigger as I expect:


The behavior i want is a color animation when pressed, and that occurs successfully, but not with the background, only the outer boarder. And the background of target name Border does indeed change on press, but only if I put it in a plain setter in the Trigger block, so it isnt as if the background change is being overridden outside the template. Thanks for any suggestions.

EDIT: Decided to add entire template and example of button employing the style. The code below has the version of the trigger that works, a simple setter targeting the problem child property.

<Style x:Key="CustomButton" TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="Grid">
<Border x:Name="Border" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
/>

<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True"/>
</Grid>
<ControlTemplate.Triggers>

<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="{StaticResource OnHoverBrush}" TargetName="Border"/>
</Trigger>
<Trigger Property="IsEnabled" Value="true">
<Setter Property="BorderBrush" Value="#898989" TargetName="Border"/>
</Trigger>


<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" Value="{StaticResource CustomDisableBrush}" TargetName="Border" />
<Setter Property="BorderBrush" Value="#898989" TargetName="Border"/>
<Setter Property="Foreground" Value="Gray"/>
</Trigger>

<Trigger Property="IsPressed" Value="True" >
<Setter Property="Background" TargetName="Border" Value="Linen"/>
</Trigger>

</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


AND A BUTTON

<Button x:Name="button0" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Focusable="False" FontSize="40"
Click="OnNumberKeyClick" Style="{StaticResource CustomButton}">
<Button.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFFAF3F3" Offset="0"/>
<GradientStop Color="#FFDDDDDD" Offset="0.5"/>
<GradientStop Color="#FF7A8197" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
<!--BUTTON CONTENT-->
<Viewbox Stretch="Uniform">
<TextBlock Text= "0"/>
</Viewbox>
</Button>

Answer Source

When I compile targeting .NET 4.0 and above. Your code works fine.

But for .NET 3.5, It seems like Border.Background has no default value (.NET 4.0 and above default is Transparent). Hence, you need to set its value first to a SolidColorBrush. MSDN Border.Background.

Property Value Type: System.Windows.Media.Brush The Brush that draws the background. This property has no default value.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download