WPF:从code动画TranslateTransform [英] WPF: Animating TranslateTransform from code

查看:414
本文介绍了WPF:从code动画TranslateTransform的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WPF画布上,我动态创建从code对象。这些目的是由设置RenderTransform属性转化和动画需要施加这些变换中的一个。任何目前,我不能得到性变换动画(虽然也不例外得到提高,动画将运行 - 完成事件引发获取)。

此外,如果在动画系统被强调,有时Storyboard.Completed事件从未提出。

我来翻过所有的例子动画从XAML的转换。 MSDN文档表明,X:的Name属性转换必须为它设置成将动画,但我还没有发现从code设置工作方式。

任何想法?

下面是能重现问题的全部code房源的:

 使用系统;
使用System.Diagnostics程序;
使用System.Windows;
使用System.Windows.Controls的;
使用System.Windows.Input;
使用System.Windows.Media;
用System.Windows.Media.Animation;
使用System.Windows.Shapes;命名空间AnimationCompletedTest {
    ///<总结>
    ///为MainWindow.xaml交互逻辑
    ///< /总结>
    公共部分类主窗口:窗口{        画布面板;
        公共主窗口(){
            的InitializeComponent();
            的MouseDown + = DoDynamicAnimation;            内容= =面板新画布();
        }        无效DoDynamicAnimation(对象发件人,MouseButtonEventArgs参数){            的for(int i = 0; I< 12; ++ I){
                变种E =新的椭圆{
                    宽度= 16,
                    高度= 16,
                    填写= SystemColors.HighlightBrush
                };
                Canvas.SetLeft(即Mouse.GetPosition(本).X);
                Canvas.SetTop(即Mouse.GetPosition(本).Y);                VAR TG =新的TransformGroup();
                变种翻译=新TranslateTransform(30,0);
                tg.Children.Add(翻译);
                tg.Children.Add(新RotateTransform(我* 30));
                e.RenderTransform = TG;                panel.Children.Add(E);                变种S =新的故事板();
                Storyboard.SetTarget(S,翻译);
                Storyboard.SetTargetProperty(S,新的PropertyPath(TranslateTransform.XProperty));                s.Children.Add(
                    新DoubleAnimation是(3,100,新持续时间(新时间跨度(0,0,0,1,0))){
                        的easingFunction =新PowerEase {EasingMode = EasingMode.EaseOut}
                    });                s.Completed + =
                    (SNDR,evtArgs)= GT; {
                        的Debug.WriteLine(动漫{0}完成{1},s.GetHash code(),Stopwatch.GetTimestamp());
                        panel.Children.Remove(E);
                    };                的Debug.WriteLine(动漫{0}开始{1},s.GetHash code(),Stopwatch.GetTimestamp());                s.Begin();
            }
        }        [STAThread]
        公共静态无效的主要(){
            VAR应用=新的应用程序();
            app.Run(新主窗口());
        }
    }
}


解决方案

似乎有点谷歌搜索后,我解决了自己的问题。非常感谢 MSDN文档和<一个href=\"http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/594c9b9b-624b-42d1-99ad-b5084f5f5325\">a通过Antares19 张贴在MSDN论坛。

在总结:


  • 有关可冷冻的物品(如TranslateTransform)由一个故事板是定位的,它必须有一个注册的名称。这可以通过调用FrameworkElement.RegisterName(..)来完成。


  • 我添加故事板对象相同的框架元素的ResourceDictionary到我注册的TranslateTransform。这可以通过调用ResourceDictionary.Add(..)来完成


下面是更新code,现在很好的动画,并注册/注销该添加的资源:

 使用系统;
使用System.Windows;
使用System.Windows.Controls的;
使用System.Windows.Input;
使用System.Windows.Media;
用System.Windows.Media.Animation;
使用System.Windows.Shapes;命名空间AnimationCompletedTest {    公共部分类主窗口:窗口{        画布面板;
        公共主窗口(){
            的InitializeComponent();
            的MouseDown + = DoDynamicAnimation;            内容= =面板新画布();
        }        无效DoDynamicAnimation(对象发件人,MouseButtonEventArgs参数){
            的for(int i = 0; I&LT; 12; ++ I){
                变种E =新的椭圆{宽度= 16,身高= 16,填充= SystemColors.HighlightBrush};
                Canvas.SetLeft(即Mouse.GetPosition(本).X);
                Canvas.SetTop(即Mouse.GetPosition(本).Y);                VAR TG =新的TransformGroup();
                变种翻译=新TranslateTransform(30,0);
                VAR translationName =myTranslation+ translation.GetHash code();
                RegisterName(translationName,翻译);
                tg.Children.Add(翻译);
                tg.Children.Add(新RotateTransform(我* 30));
                e.RenderTransform = TG;                panel.Children.Add(E);                变种阿尼姆=新DoubleAnimation是(3,100,新持续时间(新时间跨度(0,0,0,1,0))){
                    的easingFunction =新PowerEase {EasingMode = EasingMode.EaseOut}
                };                变种S =新的故事板();
                Storyboard.SetTargetName(S,translationName);
                Storyboard.SetTargetProperty(S,新的PropertyPath(TranslateTransform.YProperty));
                VAR STORYBOARDNAME =S+ s.GetHash code();
                Resources.Add(STORYBOARDNAME,S);                s.Children.Add(阿尼姆);                s.Completed + =
                    (SNDR,evtArgs)= GT; {
                        panel.Children.Remove(E);
                        Resources.Remove(STORYBOARDNAME);
                        UnregisterName(translationName);
                    };
                s.Begin();
            }
        }        [STAThread]
        公共静态无效的主要(){
            VAR应用=新的应用程序();
            app.Run(新主窗口());
        }
    }
}

I have a WPF canvas on which I'm dynamically creating objects from code. These objects are being transformed by setting the RenderTransform property, and an animation needs to be applied one of those transforms. Currently, I can't get properties of any transform to animate (although no exception gets raised and the animation appears to run - the completed event gets raised).

In addition, if the animation system is stressed, sometimes the Storyboard.Completed event is never raised.

All the examples I've come accross animate the transforms from XAML. MSDN documentation suggests that the x:Name property of a transform must be set for it to be animatable, but I haven't found a working way to set it from code.

Any ideas?

Here's the full code listing that reproduces the problem:

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace AnimationCompletedTest {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {

        Canvas panel;
        public MainWindow() {
            InitializeComponent();
            MouseDown += DoDynamicAnimation;

            Content = panel = new Canvas();
        }

        void DoDynamicAnimation(object sender, MouseButtonEventArgs args) {

            for (int i = 0; i < 12; ++i) {
                var e = new Ellipse {
                    Width = 16,
                    Height = 16,
                    Fill = SystemColors.HighlightBrush
                };
                Canvas.SetLeft(e, Mouse.GetPosition(this).X);
                Canvas.SetTop(e, Mouse.GetPosition(this).Y);

                var tg = new TransformGroup();
                var translation = new TranslateTransform(30, 0);
                tg.Children.Add(translation);
                tg.Children.Add(new RotateTransform(i * 30));
                e.RenderTransform = tg;

                panel.Children.Add(e);

                var s = new Storyboard();
                Storyboard.SetTarget(s, translation);
                Storyboard.SetTargetProperty(s, new PropertyPath(TranslateTransform.XProperty));

                s.Children.Add(
                    new DoubleAnimation(3, 100, new Duration(new TimeSpan(0, 0, 0, 1, 0))) {
                        EasingFunction = new PowerEase {EasingMode = EasingMode.EaseOut}
                    });

                s.Completed += 
                    (sndr, evtArgs) => {
                        Debug.WriteLine("Animation {0} completed {1}", s.GetHashCode(), Stopwatch.GetTimestamp());
                        panel.Children.Remove(e);
                    };

                Debug.WriteLine("Animation {0} started {1}", s.GetHashCode(), Stopwatch.GetTimestamp());

                s.Begin();
            }
        }

        [STAThread]
        public static void Main() {
            var app = new Application();
            app.Run(new MainWindow());
        }
    }
}

解决方案

Seems that after a bit of Googling I solved the problem myself. Many thanks to MSDN documentation and a post in MSDN forums by Antares19.

In summary:

  • For a Freezable object (like TranslateTransform) to be targetable by an Storyboard, it must have a registered name. This can be done by calling FrameworkElement.RegisterName(..).

  • I added the Storyboard object to the ResourceDictionary of the same Framework element to which I registered the TranslateTransform. This can be done by calling ResourceDictionary.Add(..)

Here's the updated code, which now animates nicely, and registers/deregisters the added resources:

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

namespace AnimationCompletedTest {

    public partial class MainWindow : Window {

        Canvas panel;
        public MainWindow() {
            InitializeComponent();
            MouseDown += DoDynamicAnimation;

            Content = panel = new Canvas();
        }

        void DoDynamicAnimation(object sender, MouseButtonEventArgs args) {
            for (int i = 0; i < 12; ++i) {
                var e = new Ellipse { Width = 16, Height = 16, Fill = SystemColors.HighlightBrush };
                Canvas.SetLeft(e, Mouse.GetPosition(this).X);
                Canvas.SetTop(e, Mouse.GetPosition(this).Y);

                var tg = new TransformGroup();
                var translation = new TranslateTransform(30, 0);
                var translationName = "myTranslation" + translation.GetHashCode();
                RegisterName(translationName, translation);
                tg.Children.Add(translation);
                tg.Children.Add(new RotateTransform(i * 30));
                e.RenderTransform = tg;

                panel.Children.Add(e);

                var anim = new DoubleAnimation(3, 100, new Duration(new TimeSpan(0, 0, 0, 1, 0))) {
                    EasingFunction = new PowerEase { EasingMode = EasingMode.EaseOut }
                };

                var s = new Storyboard();
                Storyboard.SetTargetName(s, translationName);
                Storyboard.SetTargetProperty(s, new PropertyPath(TranslateTransform.YProperty));
                var storyboardName = "s" + s.GetHashCode();
                Resources.Add(storyboardName, s);

                s.Children.Add(anim);

                s.Completed +=
                    (sndr, evtArgs) => {
                        panel.Children.Remove(e);
                        Resources.Remove(storyboardName);
                        UnregisterName(translationName);
                    };
                s.Begin();
            }
        }

        [STAThread]
        public static void Main() {
            var app = new Application();
            app.Run(new MainWindow());
        }
    }
}

这篇关于WPF:从code动画TranslateTransform的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆