Animating nested children's properties using a style [WPF]

76 views Asked by At

I have a button with an image in it. The image's source is just an SVG that I have converted into XAML code. How do I animate the color of that SVG.

I want to create a style that changes the color of the image that I can use on all buttons with SVG images.

Here is the button's code:

<Button Background="Transparent"
                                BorderThickness="0"
                                Style="{StaticResource VideoControl}">
                            <Image>
                                <Image.Source>
                                    <DrawingImage>
                                        <DrawingImage.Drawing>
                                            <DrawingGroup ClipGeometry="M0,0 V29 H26 V0 H0 Z">
                                                <DrawingGroup.Children>
                                                    <GeometryDrawing Brush="White" Geometry="F1 M26,29z M0,0z M24,11.0359C26.6667,12.5755,26.6667,16.4245,24,17.9641L6.75,27.9234C4.08334,29.463,0.75,27.5385,0.75,24.4593L0.75,4.54071C0.75,1.46151,4.08333,-0.462994,6.75,1.07661L24,11.0359z" />
                                                </DrawingGroup.Children>
                                            </DrawingGroup>
                                        </DrawingImage.Drawing>
                                    </DrawingImage>
                                </Image.Source>
                            </Image>
                        </Button>

Here is my attempt:

<Style TargetType="Button" x:Key="VideoControl">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0"/>

            <!--This is done to prevent the Window Control Buttons from being focused-->
            <Setter Property="Focusable" Value="False"/>

            <!--This overrides the default behaviour of the button when hovering over it-->
            <Setter Property="OverridesDefaultStyle" Value="True"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Name="border" 
                                Padding="0"
                                Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <!--Animations-->
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation
                                    Storyboard.TargetProperty=""
                                    To="#F0AD2B"
                                    Duration="0:0:0.2"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                </Trigger>
            </Style.Triggers>
        </Style>

As you can see. I tried fiddling around with Storyboard.TargetProperty but I couldn't reach the bursh's color of the image source.

2

There are 2 answers

1
Clemens On BEST ANSWER

You could bind the GeometryDrawing's Brush to the Foreground property of the Button

<GeometryDrawing
    Brush="{Binding Foreground,
            RelativeSource={RelativeSource AncestorType=Button}}"
    .../>

and animate that property

<Style TargetType="Button" x:Key="VideoControl">
    ...
    <Setter Property="Foreground">
        <Setter.Value>
            <SolidColorBrush Color="White"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Trigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <ColorAnimation
                            Storyboard.TargetProperty="Foreground.Color"
                            To="#F0AD2B"
                            Duration="0:0:0.2"/>
                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
        </Trigger>
    </Style.Triggers>
</Style>

There should also be a <Trigger.ExitActions> that stops the BeginStoryboard or animates back to white.

1
AudioBubble On

You should bind the Brush to a property of the Button. The below example uses the Foreground property. If you want to decouple the color of the image from the Button.Foreground you should extend Button and create an ImageButton that defines e.g. ImageForeground and ImageBackground properties that you can bind to instead.

Then use an EventTrigger to animate on MouseEnter (to start the animation) and MouseLeave (to stop the animation using a StopStoryboard or to revert the animation using a BeginStoryboard). The ColorAnimation target is the Button.Foreground.Color property (the SolidColorBrush.Color property).

<!-- Control the image color by setting the Foreground property -->
<Button Background="Transparent"
        Foreground="OrangeRed"
        BorderThickness="0">

  <!-- Dynamic content -->
  <Image>
    <Image.Source>
      <DrawingImage>
        <DrawingImage.Drawing>
          <DrawingGroup ClipGeometry="M0,0 V29 H26 V0 H0 Z">
            <DrawingGroup.Children>
              <GeometryDrawing Brush="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=Foreground}"
                               Geometry="F1 M26,29z M0,0z M24,11.0359C26.6667,12.5755,26.6667,16.4245,24,17.9641L6.75,27.9234C4.08334,29.463,0.75,27.5385,0.75,24.4593L0.75,4.54071C0.75,1.46151,4.08333,-0.462994,6.75,1.07661L24,11.0359z" />
            </DrawingGroup.Children>
          </DrawingGroup>
        </DrawingImage.Drawing>
      </DrawingImage>
    </Image.Source>
  </Image>

  <Button.Style>

    <!-- Reusable Style -->
    <Style TargetType="Button">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Border Name="border"
                    Padding="0"
                    Background="{TemplateBinding Background}">
              <ContentPresenter HorizontalAlignment="Center"
                                VerticalAlignment="Center" />
            </Border>

            <ControlTemplate.Triggers>
              <EventTrigger RoutedEvent="MouseEnter">
                <BeginStoryboard x:Name="MouseOverAnimation">
                  <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="Foreground.(SolidColorBrush.Color)"
                                    To="#F0AD2B"
                                    Duration="0:0:0.2" />
                  </Storyboard>
                </BeginStoryboard>
              </EventTrigger>

              <EventTrigger RoutedEvent="MouseLeave">
                <StopStoryboard BeginStoryboardName="MouseOverAnimation" />
              </EventTrigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Button.Style>
</Button>