代码之家  ›  专栏  ›  技术社区  ›  Grégory Ranson

如何在ToggleButton动画上添加自定义绑定

  •  0
  • Grégory Ranson  · 技术社区  · 7 年前

    我有一个模板 ToggleButton

    <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>
    

    我想编辑 ColorAnimation 切换按钮 这种方式:

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

    切换按钮 DependencyProperty 这样地:

    <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>
    

    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));
    

    当我尝试使用此选项时:

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

    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')
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   mm8    7 年前

    你不能绑定到 To ColorAnimation 由于性能原因,动画被冻结: https://social.msdn.microsoft.com/Forums/vstudio/en-US/027c364f-5d75-424f-aafd-7fb76b10b676/templatebinding-on-storyboard?forum=wpf

    您可以参考以下类似问题以获取一些建议:

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

    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>