c# - MouseEnter 事件上的按钮背景没有动画
问题描述
我想用 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 方法中获得了正确的颜色。但是按钮的背景没有改变
但是,ButtonOnMouseLeave 方法中的动画可以正常工作!
为什么这样?
解决方案
按钮模板中使用的ClipBorder中的问题。更改为边框并开始工作
推荐阅读
- opencv - OpenCV:特征匹配+单应性帮助调整结果
- cloudera-cdh - 从 Knox 访问 Cloudera 上的 kerberized WebHDFS
- docusignapi - 无法在开发人员沙箱中创建新的集成商密钥
- perl - 如何从命令行测试 Perl CGI 脚本以进行文件上传?
- css - 使用纯 CSS 对悬停的简单窗帘效果
- android - react-navigation + redux 当我按下 Android 后退按钮时。应用程序被杀死而不是向后动作
- node.js - ejs模板表达式中的ejs模板表达式(不包括)
- scala - 如何打印使用 SBT 构建项目的测试配置中的所有设置?
- android - 如何将数据从 Activity 发送到 Widget?
- java - 是否可以使用 Resteasy 发布 byte[] 来调用 rest api?