按钮背景在MouseEnter事件上未设置动画

时间:2018-12-30 17:20:00

标签: c# wpf animation colors

我想用DinamicResources为按钮的背景色设置动画。为此,我创建了附加的DependencyProperty:

namespace ModPlusStyle.Controls.Helpers
{
    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;

    public class ButtonAssist
    {
        private static readonly Dictionary<Button, Color> _initBackgroundBrush = new Dictionary<Button, Color>();

        private static readonly Dictionary<Button, Color> _initForegroundBrush = new Dictionary<Button, Color>();

        public static readonly DependencyProperty AnimateMouseOverProperty = DependencyProperty.RegisterAttached(
            "AnimateMouseOver",
            typeof(bool),
            typeof(ButtonAssist),
            new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.AffectsRender, AnimateMouseOverChangedCallback));

        public static void SetAnimateMouseOver(DependencyObject element, bool value)
        {
            element.SetValue(AnimateMouseOverProperty, value);
        }

        public static bool GetAnimateMouseOver(DependencyObject element)
        {
            return (bool)element.GetValue(AnimateMouseOverProperty);
        }

        private static void AnimateMouseOverChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is Button button)
            {
                if ((bool)e.NewValue)
                {
                    button.MouseEnter += ButtonOnMouseEnter;
                    button.MouseLeave += ButtonOnMouseLeave;
                }
                else
                {
                    button.MouseEnter -= ButtonOnMouseEnter;
                    button.MouseLeave -= ButtonOnMouseLeave;
                }
            }
        }

        private static void ButtonOnMouseEnter(object sender, MouseEventArgs e)
        {
            if (sender is Button button &&
                !(button.Parent is WindowCommands) &&
                button.Background is SolidColorBrush backgroundSolidColorBrush &&
                button.Foreground is SolidColorBrush foregroundSolidColorBrush)
            {
                var parentWindow = Window.GetWindow(button);
                if (parentWindow != null)
                {
                    if (parentWindow.Resources["WhiteBrush"] is SolidColorBrush whiteBrush &&
                        parentWindow.Resources["BlackBrush"] is SolidColorBrush blackBrush)
                    {
                        if (_initBackgroundBrush.ContainsKey(button))
                            _initBackgroundBrush[button] = backgroundSolidColorBrush.Color;
                        else
                            _initBackgroundBrush.Add(button, backgroundSolidColorBrush.Color);

                        if (_initForegroundBrush.ContainsKey(button))
                            _initForegroundBrush[button] = foregroundSolidColorBrush.Color;
                        else
                            _initForegroundBrush.Add(button, foregroundSolidColorBrush.Color);

                        button.Background = new SolidColorBrush(backgroundSolidColorBrush.Color);
                        ColorAnimation backgroundColorAnimation = new ColorAnimation(
                            backgroundSolidColorBrush.Color,
                            whiteBrush.Color,
                            new Duration(TimeSpan.FromMilliseconds(300)));
                        button.Background.BeginAnimation(SolidColorBrush.ColorProperty, backgroundColorAnimation);

                        button.Foreground = new SolidColorBrush(foregroundSolidColorBrush.Color);
                        ColorAnimation foregroundColorAnimation = new ColorAnimation(
                            foregroundSolidColorBrush.Color,
                            blackBrush.Color,
                            new Duration(TimeSpan.FromMilliseconds(300)));
                        button.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, foregroundColorAnimation);
                    }
                }
            }
        }

        private static void ButtonOnMouseLeave(object sender, MouseEventArgs e)
        {
            if (sender is Button button &&
                !(button.Parent is WindowCommands) &&
                _initBackgroundBrush.ContainsKey(button) &&
                _initForegroundBrush.ContainsKey(button))
            {
                var parentWindow = Window.GetWindow(button);
                if (parentWindow != null)
                {
                    if (parentWindow.Resources["AccentColorBrush"] is SolidColorBrush accentColorBrush && 
                        parentWindow.Resources["ForegroundForAccentedBrush"] is SolidColorBrush foregroundForAccentedBrush)
                    {
                        button.Background = new SolidColorBrush(((SolidColorBrush)button.Background).Color);
                        ColorAnimation backgroundColorAnimation = new ColorAnimation(
                            ((SolidColorBrush)button.Background).Color,
                            _initBackgroundBrush[button],
                            new Duration(TimeSpan.FromMilliseconds(300)));
                        backgroundColorAnimation.Completed += (o, args) =>
                        {
                            if (_initBackgroundBrush[button] == accentColorBrush.Color)
                                button.SetResourceReference(Control.BackgroundProperty, "AccentColorBrush");
                            _initBackgroundBrush.Remove(button);
                        };
                        button.Background.BeginAnimation(SolidColorBrush.ColorProperty, backgroundColorAnimation);

                        button.Foreground = new SolidColorBrush(((SolidColorBrush)button.Foreground).Color);
                        ColorAnimation foregroundColorAnimation = new ColorAnimation(
                            ((SolidColorBrush)button.Foreground).Color,
                            _initForegroundBrush[button],
                            new Duration(TimeSpan.FromMilliseconds(300)));
                        foregroundColorAnimation.Completed += (o, args) =>
                        {
                            if (_initForegroundBrush[button] == foregroundForAccentedBrush.Color)
                                button.SetResourceReference(Control.ForegroundProperty, "ForegroundForAccentedBrush");
                            _initForegroundBrush.Remove(button);
                        };
                        button.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, foregroundColorAnimation);
                    }
                }
            }
        }
    }
}

我以按钮样式设置值:

<Style x:Key="ModPlusAccentButton" TargetType="{x:Type ButtonBase}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
    <Setter Property="Background" Value="{DynamicResource AccentColorBrush}" />
    <Setter Property="BorderBrush" Value="{DynamicResource AccentColorBrush}" />
    <Setter Property="Foreground" Value="{DynamicResource ForegroundForAccentedBrush}" />
    <Setter Property="Padding" Value="12 6 12 6" />
    <Setter Property="helpers:ButtonAssist.AnimateMouseOver" Value="True"></Setter>
    <Setter Property="SnapsToDevicePixels" Value="True" />
    .......

在调试中,我在ButtonOnMouseEnter方法中获得了正确的颜色。但是按钮的背景没有改变 jig example

但是,ButtonOnMouseLeave方法中的动画可以正常工作!

为什么呢?

1 个答案:

答案 0 :(得分:0)

在按钮模板中使用的ClipBorder中的问题。更改为边界,它开始工作