0

I have a template for ToggleButton looking like this:

<Window.Resources>
        <Style TargetType="ToggleButton">
            <Setter Property="Foreground" Value="#58585a"/>
            <Setter Property="Padding" Value="3"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="#58585a">
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Grid>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="MouseOver"/>
                                    <VisualState x:Name="Pressed"/>
                                    <VisualState x:Name="Disabled"/>
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="CheckStates">
                                    <VisualState x:Name="Checked">
                                        <Storyboard>
                                            <ColorAnimation To="Green" Storyboard.TargetName="BackgroundGrid" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)" /> // Bind the color to BackgroundChecked
                                            <ColorAnimation To="White" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"/> // Bind the color to ForegroundChecked
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Unchecked"/>
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="FocusStates">
                                    <VisualState x:Name="Unfocused" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="Background" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
                                <Grid x:Name="BackgroundGrid" Background="Transparent" Margin="1"/>
                            </Border>
                            <ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

I want to edit the ColorAnimation in the Checked VisualState so as to using the ToggleButton this way :

<ToggleButton BackgroundChecked="Green" ForegroundChecked="White">Green</ToggleButton> 

What is the way to achieve that ?

Edit :

I've templated my own ToggleButton and defined his DependencyProperty like this :

<ToggleButton x:Name="root" x:Class="WpfApplicationTest.ToggleButtonColor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplicationTest"
             mc:Ignorable="d" 
             d:DesignHeight="40" d:DesignWidth="100">
    <ToggleButton.Template>
        <ControlTemplate
                 TargetType="{x:Type ToggleButton}">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal" />
                        <VisualState x:Name="MouseOver"/>
                        <VisualState x:Name="Pressed" />
                        <VisualState x:Name="Disabled"/>
                    </VisualStateGroup>
                    <VisualStateGroup x:Name="CheckStates">
                        <VisualState x:Name="Checked">
                            <Storyboard>
                                <ColorAnimation To="{Binding BackgroundChecked, ElementName=root}" Storyboard.TargetName="BackgroundBrush" Storyboard.TargetProperty="Color" />
                            </Storyboard>
                        </VisualState>
                        <VisualState x:Name="Unchecked" />
                        <VisualState x:Name="Indeterminate" />
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <Border x:Name="Border" BorderThickness="1" BorderBrush="#58585a">
                    <Border.Background>
                        <SolidColorBrush x:Name="BackgroundBrush" Color="Transparent"/>
                    </Border.Background>
                </Border>
                <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" TextBlock.Foreground="#58585a" TextBlock.FontSize="12"/>
            </Grid>
        </ControlTemplate>
    </ToggleButton.Template>
</ToggleButton>

and this :

public Color BackgroundChecked
        {
            get { return (Color)GetValue(BackgroundCheckedProperty); }
            set { SetValue(BackgroundCheckedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for BackgroundChecked.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BackgroundCheckedProperty =
            DependencyProperty.Register("BackgroundChecked", typeof(Color), typeof(ToggleButton));

When i try to use this :

<local:ToggleButtonColor BackgroundChecked="Red" BorderBrush="#58585a" BorderThickness="1" Width="100" Height="50" Content="test"></local:ToggleButtonColor>

I have this error :

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=BackgroundChecked; DataItem=null; target element is 'ColorAnimation' (HashCode=27433049); target property is 'To' (type 'Nullable`1')
  • They're not yet defined, i think i have to define DependencyProperty but i don't know how to. The goal is to have a StackPanel with 6 ToggleButton associated each one to a color. – Grégory Ranson Aug 24 '17 at 09:51
  • So what is your question? How to define a dependency property? You should narrow down your question a bit. – mm8 Aug 24 '17 at 09:51
  • @mm8 I've take some time to review my problem and edit my question to add a more precise example. Now, i've the binding but that doesn't work. – Grégory Ranson Aug 24 '17 at 13:41

1 Answers1

0

You can't bind to the To property of a ColorAnimation because the animation is frozen for performance reasons: https://social.msdn.microsoft.com/Forums/vstudio/en-US/027c364f-5d75-424f-aafd-7fb76b10b676/templatebinding-on-storyboard?forum=wpf

You could refer to the following similar question for some suggestions:

WPF animation: binding to the "To" attribute of storyboard animation

Instead of trying to bind in XAML, you could also create the animation programmatically:

public class ToggleButtonColor  : ToggleButton
{
    public Color BackgroundChecked
    {
        get { return (Color)GetValue(BackgroundCheckedProperty); }
        set { SetValue(BackgroundCheckedProperty, value); }
    }

    public static readonly DependencyProperty BackgroundCheckedProperty =
        DependencyProperty.Register("BackgroundChecked", typeof(Color), typeof(ToggleButton));

    public ToggleButtonColor()
    {
        Checked += MyToggleButton_Checked;
    }

    private void MyToggleButton_Checked(object sender, RoutedEventArgs e)
    {
        ColorAnimation colorAnimation = new ColorAnimation();
        colorAnimation.To = BackgroundChecked;
        Storyboard.SetTarget(colorAnimation, this);
        Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("Background.Color"));
        Storyboard sb = new Storyboard();
        sb.Children.Add(colorAnimation);
        sb.Begin();
    }
}

XAML:

<local:ToggleButtonColor Content="test" BackgroundChecked="Red">
    <local:ToggleButtonColor.Style>
        <Style TargetType="local:ToggleButtonColor">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:ToggleButtonColor">
                        <Border x:Name="Border" BorderThickness="1" BorderBrush="#58585a" Background="{TemplateBinding Background}">
                            <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" TextBlock.Foreground="#58585a" TextBlock.FontSize="12"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </local:MyToggleButton.Style>
</local:MyToggleButton>
mm8
  • 163,881
  • 10
  • 57
  • 88