web-dev-qa-db-de.com

Wpf animiert die Hintergrundfarbe

Ich brauche Hilfe bei der richtigen Entscheidung. Ich muss eine Hintergrundfarbe meines Benutzersteuerelements animieren, wenn ein Ereignis auftritt. Wenn dies der Fall ist, möchte ich den Hintergrund nur für 1 Sekunde ändern und dann zurückdrehen. Welchen Weg soll ich gehen? Verwenden Sie eine Farbanimation oder einen Timer oder auf andere Weise.

Gelöst Dank an alle! Das funktioniert gut für mich:

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

Ich würde eine EventTrigger mit einer ColorAnimation verwenden.

In diesem Beispiel wird ein Button Brackground bei einem MouseLeave-Ereignis grün. Dieser Code ähnelt hoffentlich dem, was Sie benötigen.

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

Achtung, Sie könnten eine System.InvalidOperationException erhalten, wenn Ihr Hintergrund eine eingefrorene Instanz ist.

Die 'Color'-Eigenschaft kann nicht unter' System.Windows.Media.SolidColorBrush 'animiert werden, da das Objekt versiegelt oder eingefroren ist.

Um diese Meldung zu korrigieren, weisen Sie den Hintergrund Ihres Steuerelements einer nicht eingefrorenen Instanz zu.

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

Freezable Objects - Übersicht auf MSDN

25
Guish
        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 sind Klasse von Color, timeSpan ist Klasse von TimeSpan, BackGroundCellGrid ist Klasse von Grid;

// keine Notwendigkeit, SolidColorBrush zu erstellen und in XAML daran zu binden; //habe Spaß!

6
DragonX

Hier finden Sie eine Reihe angefügter Eigenschaften, die verwendet werden können, wenn Sie Probleme mit Freezables haben.

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

Verwendungszweck:

<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>
1
Johan Larsson

Dieser Beitrag hat mir geholfen. Aber wenn es die Farbe nach 1 Sekunde wieder ändern soll, wie die ursprüngliche Frage sagt,

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

In WPF ist die Verwendung von Animationen möglicherweise besser. Ausdrucksmischung hat die relative Animation/Verhalten.

0
Wendy369

Das hat gut für mich funktioniert.

Ich habe einen Pfad innerhalb eines Buttons (er zeichnet ein "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"/>

Beim Mauszeiger möchte ich, dass das Kreuz rot wird, und ich füge hinzu:

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

Das verwirrendste daran sind die Klammern in Storyboard.TargetProperty. Wenn Sie die Klammern entfernen, funktioniert nichts. 

Weitere Informationen finden Sie unter " propertyName Grammar " und " Storyboard.TargetProperty ".

0
Contango