Wpf 动画背景颜色

Posted

技术标签:

【中文标题】Wpf 动画背景颜色【英文标题】:Wpf animate background color 【发布时间】:2012-12-18 23:19:18 【问题描述】:

我需要帮助才能做出正确的决定。当某些事件发生时,我需要为我的用户控件的背景颜色设置动画。当它是时,我只想改变背景 1 秒钟,然后再把它转回来。我应该走哪条路?使用彩色动画或计时器,或者可以通过其他方式。

解决了。谢谢大家!这对我很有用:

        ColorAnimation animation;
        animation = new ColorAnimation();
        animation.From = Colors.Orange;
        animation.To = Colors.Gray;
        animation.Duration = new Duration(TimeSpan.FromSeconds(1));
        this.elGrid.Background.BeginAnimation(SolidColorBrush.ColorProperty, animation);

【问题讨论】:

问题是非常开放的,因为它往往更多的是个人选择。我建议重新措辞问题或包括您尝试过的事情。 对不起,我添加了一个标签“动画”,它看起来像是自动更改的。 您至少应该发布一些代码/更多信息(哪个事件?您的 xaml 是什么样的?) 【参考方案1】:

在 WPF 中,使用动画可能会更好。表情混合具有相关的动画/行为。

【讨论】:

【参考方案2】:

您可以使用DoubleAnimation 更改颜色,如下所示:

<Storyboard>
    <DoubleAnimation Storyboard.TargetProperty="Background"
                            From="0.0"
                            Duration="0:0:2"
                            To="1.0" />                        
</Storyboard>

希望对你有帮助

【讨论】:

其实Background是一个Brush类型。 DoubleAnimation 用于为双精度类型设置动画。 这是真的 Kaus78。我从之前为 Label 控件定义的 ControlTemplate 中提取了这个 sn-p,并将 Opacity 替换为 Background 只是为了一个简单的示例。【参考方案3】:

我会使用EventTriggerColorAnimation

在此示例中,Button BrackgroundMouseLeave 事件中变为绿色。希望此代码与您可能需要的代码相似。

<Button Content="Button" Height="75" HorizontalAlignment="Left" Margin="27,12,0,0" Name="btnImgBrush" VerticalAlignment="Top" Width="160" Background="LightGray">
    <Button.Triggers>
        <EventTrigger RoutedEvent="Button.MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation To="Green" 
                                    Storyboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)" 
                                    FillBehavior="Stop" 
                                    Duration="0:0:1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Button.Triggers>
</Button>

【讨论】:

我的 XAML 无效,应该将 Duration 改为 0:0:1 吗? @Klaus78 (Button.Background).(SolidColorBrush.Color) 是什么意思?这里的括号作用是什么?? @Helic 我自己也这么问过。 MSDN 声明这是一个Single Property, Attached or Otherwise Type-Qualified 声明,请参阅docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/… 最适合填充属性。非常感谢, 尝试在 TargetProperty 上执行此操作:Storyboard.TargetProperty="(Control.Background).(SolidColorBrush.Color)",将 Button.Background 更改为 Control.Background。效果一样【参考方案4】:

注意,如果您的背景是冻结的实例,您可能会收到 System.InvalidOperationException。

无法为“System.Windows.Media.SolidColorBrush”上的“Color”属性设置动画,因为该对象已密封或冻结。

要更正此消息,请将控件的背景分配给未冻结的实例。

// Do not use a frozen instance
this.elGrid.Background = new SolidColorBrush(Colors.Orange);
this.elGrid.Background.BeginAnimation(SolidColorBrush.ColorProperty, animation);

Freezable Objects Overview on MSDN

【讨论】:

这应该在添加到原始问题的代码中。【参考方案5】:
        ColorAnimation colorChangeAnimation = new ColorAnimation();
        colorChangeAnimation.From = VariableColour;
         colorChangeAnimation.To = BaseColour;
        colorChangeAnimation.Duration = timeSpan;

        PropertyPath colorTargetPath = new PropertyPath("(Panel.Background).(SolidColorBrush.Color)");
        Storyboard CellBackgroundChangeStory = new Storyboard();
        Storyboard.SetTarget(colorChangeAnimation, BackGroundCellGrid);
        Storyboard.SetTargetProperty(colorChangeAnimation, colorTargetPath);
        CellBackgroundChangeStory.Children.Add(colorChangeAnimation);
        CellBackgroundChangeStory.Begin();

//VariableColour & BaseColour是Color的类,timeSpan是TimeSpan的类,BackGroundCellGrid是Grid的类;

//无需在 XAML 中创建 SolidColorBrush 并绑定到它; //玩得开心!

【讨论】:

【参考方案6】:

如果遇到可冻结的问题,可以使用一组附加属性。

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

public static class Blink

    public static readonly DependencyProperty WhenProperty = DependencyProperty.RegisterAttached(
        "When",
        typeof(bool?),
        typeof(Blink),
        new PropertyMetadata(false, OnWhenChanged));

    public static readonly DependencyProperty FromProperty = DependencyProperty.RegisterAttached(
        "From",
        typeof(Color),
        typeof(Blink),
        new FrameworkPropertyMetadata(Colors.Transparent, FrameworkPropertyMetadataOptions.Inherits));

    public static readonly DependencyProperty ToProperty = DependencyProperty.RegisterAttached(
        "To",
        typeof(Color),
        typeof(Blink),
        new FrameworkPropertyMetadata(Colors.Orange, FrameworkPropertyMetadataOptions.Inherits));

    public static readonly DependencyProperty PropertyProperty = DependencyProperty.RegisterAttached(
        "Property",
        typeof(DependencyProperty),
        typeof(Blink),
        new PropertyMetadata(default(DependencyProperty)));

    public static readonly DependencyProperty DurationProperty = DependencyProperty.RegisterAttached(
        "Duration",
        typeof(Duration),
        typeof(Blink),
        new PropertyMetadata(new Duration(TimeSpan.FromSeconds(1))));

    public static readonly DependencyProperty AutoReverseProperty = DependencyProperty.RegisterAttached(
        "AutoReverse",
        typeof(bool),
        typeof(Blink),
        new PropertyMetadata(true));

    public static readonly DependencyProperty RepeatBehaviorProperty = DependencyProperty.RegisterAttached(
        "RepeatBehavior",
        typeof(RepeatBehavior),
        typeof(Blink),
        new PropertyMetadata(RepeatBehavior.Forever));

    private static readonly DependencyProperty OldBrushProperty = DependencyProperty.RegisterAttached(
        "OldBrush",
        typeof(Brush),
        typeof(Blink),
        new PropertyMetadata(null));

    public static void SetWhen(this UIElement element, bool? value)
    
        element.SetValue(WhenProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static bool? GetWhen(this UIElement element)
    
        return (bool?)element.GetValue(WhenProperty);
    

    public static void SetFrom(this DependencyObject element, Color value)
    
        element.SetValue(FromProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static Color GetFrom(this DependencyObject element)
    
        return (Color)element.GetValue(FromProperty);
    

    public static void SetTo(this DependencyObject element, Color value)
    
        element.SetValue(ToProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static Color GetTo(this DependencyObject element)
    
        return (Color)element.GetValue(ToProperty);
    

    public static void SetProperty(this UIElement element, DependencyProperty value)
    
        element.SetValue(PropertyProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static DependencyProperty GetProperty(this UIElement element)
    
        return (DependencyProperty)element.GetValue(PropertyProperty);
    

    public static void SetDuration(this UIElement element, Duration value)
    
        element.SetValue(DurationProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static Duration GetDuration(this UIElement element)
    
        return (Duration)element.GetValue(DurationProperty);
    

    public static void SetAutoReverse(this UIElement element, bool value)
    
        element.SetValue(AutoReverseProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static bool GetAutoReverse(this UIElement element)
    
        return (bool)element.GetValue(AutoReverseProperty);
    

    public static void SetRepeatBehavior(this UIElement element, RepeatBehavior value)
    
        element.SetValue(RepeatBehaviorProperty, value);
    

    [AttachedPropertyBrowsableForChildren(IncludeDescendants = false)]
    [AttachedPropertyBrowsableForType(typeof(UIElement))]
    public static RepeatBehavior GetRepeatBehavior(this UIElement element)
    
        return (RepeatBehavior)element.GetValue(RepeatBehaviorProperty);
    

    private static void OnWhenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        var property = GetProperty((UIElement)d) ?? GetDefaultProperty(d);
        if (property == null || !typeof(Brush).IsAssignableFrom(property.PropertyType))
        
            if (DesignerProperties.GetIsInDesignMode(d))
            
                if (property != null)
                
                    throw new ArgumentException($"Could not blink for d.GetType().Name.property.Name", nameof(d));
                
            

            return;
        

        AnimateBlink(e.NewValue as bool?, (UIElement)d, property);
    

    private static DependencyProperty GetDefaultProperty(DependencyObject d)
    
        if (d is Control)
        
            return Control.BackgroundProperty;
        

        if (d is Panel)
        
            return Panel.BackgroundProperty;
        

        if (d is Border)
        
            return Border.BackgroundProperty;
        

        if (d is Shape)
        
            return Shape.FillProperty;
        

        if (DesignerProperties.GetIsInDesignMode(d))
        
            throw new ArgumentException($"Could not find property to blink for d.GetType().Name", nameof(d));
        

        return null;
    

    private static void AnimateBlink(bool? blink, UIElement element, DependencyProperty property)
    
        if (element == null)
        
            return;
        
        if (blink == true)
        
            var brush = element.GetValue(property);
            element.SetCurrentValue(OldBrushProperty, brush);
            element.SetValue(property, Brushes.Transparent);
            var from = element.GetFrom();
            var to = element.GetTo();
            var sb = new Storyboard();
            var duration = element.GetDuration();
            var animation = new ColorAnimation(from, to, duration)
            
                AutoReverse = element.GetAutoReverse(),
                RepeatBehavior = element.GetRepeatBehavior()
            ;
            Storyboard.SetTarget(animation, element);
            Storyboard.SetTargetProperty(animation, new PropertyPath($"property.Name.(SolidColorBrush.Color)"));
            sb.Children.Add(animation);
            sb.Begin();
        
        else
        
            var brush = element.GetValue(OldBrushProperty);
            element.BeginAnimation(property, null);
            element.SetCurrentValue(property, brush);
        
    

用法:

<Grid>
    <Grid.Resources>
        <Style x:Key="BlinkWhenMouseOver"
               TargetType="x:Type Border">
            <Setter Property="local:Blink.When" Value="Binding IsMouseOver, RelativeSource=RelativeSource Self" />
            <Setter Property="local:Blink.From" Value="Honeydew" />
            <Setter Property="local:Blink.To" Value="HotPink" />
            <Setter Property="BorderThickness" Value="5" />
            <Setter Property="local:Blink.Property" Value="x:Static Border.BorderBrushProperty" />
        </Style>
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Border Style="StaticResource BlinkWhenMouseOver" Background="Transparent"/>
    <Border Grid.Row="1"
            local:Blink.From="Aqua"
            local:Blink.To="Yellow"
            local:Blink.When="Binding IsChecked,
                                       ElementName=ToggleBlink" />
    <ToggleButton x:Name="ToggleBlink"
                  Grid.Row="2"
                  Content="Blink" />
</Grid>

【讨论】:

【参考方案7】:

这篇文章帮助了我。但是如果是像原来的问题所说的那样在 1 秒后改变颜色,

 ColorAnimation animation;
    animation = new ColorAnimation();
    animation.AutoReverse =true;

【讨论】:

【参考方案8】:

这对我很有效。

我有一个按钮内的路径(它画了一个“X”):

<Path x:Name="MyDeleteRowButton" Stroke="Gray" Grid.Row="0" 
      Data="M1,5 L11,15 M1,15 L11,5" StrokeThickness="2" HorizontalAlignment="Center" 
      Stretch="None"/>

鼠标悬停时,我想让十字变成红色,所以我添加:

<DataTemplate.Triggers>
    <!-- Highlight row on mouse over, and highlight the delete button. -->
    <EventTrigger RoutedEvent="ItemsControl.MouseEnter">
        <EventTrigger.Actions>
            <BeginStoryboard>
                <Storyboard>
                    <!-- On mouse over, flicker the row to highlight it.-->
                    <DoubleAnimation
                        Storyboard.TargetProperty="Opacity"
                        From="0.5" 
                        To="1" 
                        Duration="0:0:0.250"  
                        FillBehavior="Stop"/>
                    <!-- Highlight the delete button with red. -->
                    <ColorAnimation
                        To="Red"
                        Storyboard.TargetName="MyDeleteRowButton"
                        Storyboard.TargetProperty="(Stroke).(SolidColorBrush.Color)"
                        Duration="0:0:0.100" 
                        FillBehavior="HoldEnd"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.Actions>
    </EventTrigger>

    <!-- Grey out the delete button. -->
    <EventTrigger RoutedEvent="ItemsControl.MouseLeave">
        <EventTrigger.Actions>
            <BeginStoryboard>
                <Storyboard>
                    <!-- Space is precious: "delete" button appears only on a mouseover. -->
                    <ColorAnimation
                        To="Gray"
                        Storyboard.TargetName="MyDeleteRowButton"
                        Storyboard.TargetProperty="(Stroke).(SolidColorBrush.Color)"
                        Duration="0:0:0.100" 
                        FillBehavior="HoldEnd"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger.Actions>
    </EventTrigger>

</DataTemplate.Triggers>

最令人困惑的是Storyboard.TargetProperty 中的括号。如果删除括号,则没有任何效果。

有关详细信息,请参阅“propertyName Grammar”和“Storyboard.TargetProperty”。

【讨论】:

以上是关于Wpf 动画背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

WPF简单模拟QQ登录背景动画

WPF简单模拟QQ登录背景动画(转)

WPF 组合框禁用背景颜色

wpf按钮背景悬停颜色

更改 WPF 标题栏背景颜色

wpf中直线背景颜色问题.