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



简单地说,我在ControlTemplate.Triggers条件EnterAction中有这个:

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

但我希望'to'颜色(#fe7)是可定制的。这是一个来自ListBox的控制。我可以创建一个DependencyProperty,但当然,我不能将ColorAnimationTo属性绑定到它,因为Storyboard必须被冻结,而你不能用绑定来冻结某些东西(据我所知)。

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

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

有什么好的方法可以做到这一点吗?我是否必须求助于自己寻找属性更改,动态调用和管理故事板?或者叠加两个版本的控件,开始和结束的颜色,而不是动画不透明度?

Kieren,

这符合你的目的吗?

我已经扩展了名为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;
        }

我正在改变网格的背景颜色,因为我没有你的列表框。

最后是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();
            }
        }
    }

}

正如你所看到的,我正在获取一个对storyboard的引用并改变它的to属性。您对StaticResource的方法显然是行不通的。现在你能做的是,在你的DependencyProperty回调中以某种方式获得你想要动画的时间轴的引用并使用VisualTreeHelper或其他东西然后设置它的To属性。

这是你最好的选择。

让我知道这是否解决了你的问题:)

是否可以设置多个datatrigger,每个datatrigger的"To"属性都有各自的颜色…

当然不是…我所理解的是,你想在条件A中使用颜色A,在其他条件B中使用颜色B....如果有一个带有多个选项的属性你可以只为那些条件设置datatriggers。工作完成=红色,一半完成=绿色。如果我误解了问题,请纠正我。

我想我明白你的问题了。UR控件是用户可配置的所以无论用户选择什么,控件的背景都需要设置为带有动画的颜色,对吧?

事实证明这根本不可能。

最新更新