具有绑定属性的故事板(自定义控件:动画颜色更改)

时间:2011-10-01 14:53:07

标签: c# wpf xaml animation

简单地说,我在ControlTemplate.Triggers条件EnterAction

范围内
<ColorAnimation To="#fe7" Storyboard.TargetProperty="Background.Color" Duration="00:00:00.1" Storyboard.TargetName="brd"/>

但我希望'to'颜色(#fe7)可以自定义。这是一个源自ListBox的控件。我可以创建DependencyProperty,但当然,我无法将To的{​​{1}}属性绑定到它,因为ColorAnimation必须被冻结,您无法冻结带有绑定的东西(据我所知)。

我尝试在Storyboard中使用{StaticResource},然后在更改To时填充代码隐藏中的资源,例如设置DependencyProperty。这显然不起作用,毕竟它是一个静态资源:没有新的属性值被选中。 this.Resources["ItemColour"] = newValue;提出了与无法冻结相同的问题。

该属性仅在创建控件时设置一次,我不必担心它会在动画中期改变。

有这样做的好方法吗?我是否必须自己寻找属性更改,此时动态调用和管理故事板?或者覆盖两个版本的控件,开始和结束颜色,以及动画不透明度?两者看起来都很荒谬..

4 个答案:

答案 0 :(得分:2)

基伦,

这是否符合您的目的?

我扩展了名为CustomGrid的Grid类并创建了一个TestProperty,其值在更改时将改变Grid的背景颜色:

 public class CustomGrid : Grid
    {
        public bool Test
        {
            get
            {
                return (bool)GetValue(TestProperty);
            }
            set
            {
                SetValue(TestProperty, value);
            }
        }
        public static readonly DependencyProperty TestProperty =
            DependencyProperty.Register("Test", typeof(bool), typeof(CustomGrid),
                new PropertyMetadata(new PropertyChangedCallback
                    ((obj, propChanged) =>
                    {

                        CustomGrid control = obj as CustomGrid;
                        if (control != null)
                        {
                            Storyboard sb = new Storyboard() { Duration = new Duration(TimeSpan.FromMilliseconds(500)) };

                            Random rand = new Random();
                            Color col = new Color()
                            {
                                A = 100,
                                R = (byte)(rand.Next() % 255),
                                G = (byte)(rand.Next() % 255),
                                B = (byte)(rand.Next() % 255)
                            };


                            ColorAnimation colAnim = new ColorAnimation();

                            colAnim.To = col;
                            colAnim.Duration = new Duration(TimeSpan.FromMilliseconds(500));


                            sb.Children.Add(colAnim);
                            Storyboard.SetTarget(colAnim, control);
                            Storyboard.SetTargetProperty(colAnim, new PropertyPath("(Panel.Background).(SolidColorBrush.Color)"));

                            sb.Begin();

                        }
                    }
                )));
    }

这是更改颜色的按钮单击事件:

 private void btnClick_Click(object sender, RoutedEventArgs e)
        {
            gridCustom.Test = (gridCustom.Test == true) ? false : true;
        }

我正在更改Grid的背景颜色,因为我没有您的Listbox。

最后这是xaml:

 <Grid x:Name="grid" Background="White">
        <local:CustomGrid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" >

        </local:CustomGrid>
        <Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0"  VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
    </Grid>

这是否符合您的目的?让我知道或者我误解了这个问题?

修改

请参阅此代码:

ColorAnimation的To属性不能像你猜测的那样绑定。但这并不意味着你无法改变它的价值。您始终可以获得对ColorAnimation的引用并将其更改为To值,它将全部运行良好。所以从WPF绑定世界我们需要改变一点并绑定数据我们以前在Winforms中做的方式:)。作为一个例子,请看:

这是xaml:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="ControlTemplateTriggers.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>

        <Storyboard x:Key="Storyboard">
            <ColorAnimation From="Black" To="Red" Duration="00:00:00.500" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)" Storyboard.TargetName="gridCustom" />
        </Storyboard>
    </Window.Resources>

    <Grid x:Name="grid" Background="White">
        <Grid x:Name="gridCustom" Background="Pink" Height="100" Margin="104,109,112,102" />

        <Button Content="Click Me" x:Name="btnClick" Height="45" HorizontalAlignment="Left" Margin="104,12,0,0"  VerticalAlignment="Top" Width="145" Click="btnClick_Click" />
    </Grid>
</Window>

这是背后的代码:

using System.Windows;
using System.Windows.Media.Animation;
using System.Windows.Media;
using System;

namespace Sample    {

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

        }

        private void btnClick_Click(object sender, RoutedEventArgs e)
        {
            Storyboard sb = this.Resources["Storyboard"] as Storyboard;
            if (sb != null)
            {
                ColorAnimation frame = sb.Children[0] as ColorAnimation;
                Random rand = new Random();
                Color col = new Color()
                              {
                                  A = 100,
                                  R = (byte)(rand.Next() % 255),
                                  G = (byte)(rand.Next() % 255),
                                  B = (byte)(rand.Next() % 255)
                              };
                frame.To = col;
                sb.Begin();
            }
        }
    }


}

正如您所看到的,我正在获取对故事板的引用并将其更改为To属性。您对StaticResource的处理方法显然不起作用。现在你可以做的是,在你的DependencyProperty回调中以某种方式获得你想要动画的时间轴的引用并使用VisualTreeHelper或其他东西,然后设置它的To属性。

这是你最好的选择。

请告诉我这是否解决了您的问题:)

答案 1 :(得分:0)

你可以把多个DataTriggers分别用于“To”属性......

答案 2 :(得分:0)

当然不是.. 我理解的是你想要条件A上的颜色A和其他条件B上的颜色B ....所以如果有一个具有多个选项的属性你可以只为这些条件设置数据触发器...就像完成了工作=红色一半完成=绿色就像明智一样.. 如果我误解了这个问题,请纠正我..

我想我的问题是... UR控件是用户可配置的,所以用户选择什么,控件的背景需要设置为动画的那种颜色吗?

答案 3 :(得分:0)

事实证明这根本不可能。