【问题标题】:Storyboards with bound properties (custom control: animate colour change)具有绑定属性的情节提要(自定义控件:动画颜色更改)
【发布时间】:2012-11-26 00:17:30
【问题描述】:

简单地说,我在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 给出了与无法冻结有关的相同问题。

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

有什么好的方法吗?我是否必须自己寻找属性更改,然后动态调用和管理情节提要?或者覆盖两个版本的控件,开始颜色和结束颜色,并改为动画不透明度?两者看起来都很可笑..

【问题讨论】:

    标签: c# wpf xaml animation


    【解决方案1】:

    基伦,

    这会达到你的目的吗?

    我扩展了名为 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 属性。

    这是你最好的选择。

    如果这解决了您的问题,请告诉我:)

    【讨论】:

    • 这是我的备用技术之一:以编程方式创建故事板。我在问这个问题,看看是否有另一种方法可以实现这一目标而不必在代码隐藏中破解?
    • @KierenJohnstone:查看我的编辑。希望它能解决你的问题:)
    • 不,按照这里:msdn.microsoft.com/en-us/library/ms742868.aspx 如果您使用 Begin 调用(在代码中),您将无法为 ControlTemplate 中的属性设置动画
    • 嗯,没有办法。一切都被冻结了。事实上,控制模板中的整个 ResourceDictionary 都是只读的。您无法在任何地方进行任何更改。这个问题在某种程度上与线程安全有关:(
    【解决方案2】:

    你可以为“To”属性放置多个 DataTriggers,每个 DataTriggers 都有各自的颜色...

    【讨论】:

    • 你能再解释一下吗,我不明白?控件的用户将能够指定 00000000-ffffffff,即 40 亿种颜色中的 1 种,每种颜色一个触发器,肯定不是吗? :)
    【解决方案3】:

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

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

    【讨论】:

    • 不,谢谢,但您误会了。我说我希望动画的To 是可定制的——绑定到用户可以指定的东西。如果您能告诉我如何克服无法使用绑定的限制(因为 Storyboard 必须被冻结),请回复说明您的解决方案
    【解决方案4】:

    事实证明这是不可能的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 2017-12-22
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      相关资源
      最近更新 更多