首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

WPF,卡通片的IsAdditive属性和属性值的优先级

2013-07-20 
WPF,动画的IsAdditive属性和属性值的优先级第一段代码:DoubleAnimation widthAnimation new DoubleAnima

WPF,动画的IsAdditive属性和属性值的优先级
第一段代码:


DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.From = 75;
widthAnimation.To = 130;
widthAnimation.Duration = TimeSpan.FromSeconds(0.5);
button1.BeginAnimation(Button.WidthProperty, widthAnimation);
button1.Width = 300;


这段代码当动画执行完之后,Width属性值为130,最后一句不会起作用,因为动画的属性值的优先级高

第二段代码:

DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.From = 75;
widthAnimation.To = 130;
widthAnimation.Duration = TimeSpan.FromSeconds(0.5);
widthAnimation.IsAdditive = true;
button1.BeginAnimation(Button.WidthProperty, widthAnimation);
button1.Width = 300;


第二段代码,设置了IsAdditive 属性为true,为什么最后设置Width的代码起作用了呢?IsAdditive属性能改变优先级吗?
[解决办法]
我验证了一下,这确实是一个很奇怪的问题。
至于第二段代码,button的宽度只有在大于动画后的button的长度的时候,而且是第一次才起作用。
即,假如button1.width=50;那么是看不到效果的。
即使改成button1.Width+=300;也只有在第一次动画执行后才有效果。第二,三次就没有效果了。

我觉得第二段代码的情况不正常,难道是bug?
[解决办法]
第一个问题,是由于“动画”没有停止,详情请看:
http://msdn.microsoft.com/en-us/library/aa970493%28v=vs.100%29.aspx
里面提到的其中一个停止动画的办法是:

button1.BeginAnimation(Button.WidthProperty, null);
//这样Width就会有变化了
button1.Width = 300;



[解决办法]
对于第二个问题,DoubleAnimation.IsAdditive属性的解释是:
获取或设置一个值,该值指示是否应将目标属性的当前值与此动画的起始值相加。

[解决办法]
引用:
对于第二个问题,DoubleAnimation.IsAdditive属性的解释是:
获取或设置一个值,该值指示是否应将目标属性的当前值与此动画的起始值相加。


晕死,没打完就按错回复了。。。接着说。。。

==================================================================
我的理解是,既然设置为true,即动画值与目标属性值就需要“互动”,动画值自然不能覆盖目标属性值(overriding the base value),这里的理解是根据2楼那msdn的内容写的

WPF,卡通片的IsAdditive属性和属性值的优先级
[解决办法]



DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.From = 150;
widthAnimation.Duration = TimeSpan.FromSeconds(0.5);
button1.BeginAnimation(Button.WidthProperty, widthAnimation);
button1.Width = 300;

这个最后的设置也是起了作用的,作何解释

请仔细看 DoubleAnimation.IsAdditive属性(!!!):
http://msdn.microsoft.com/zh-cn/library/vstudio/system.windows.media.animation.doubleanimation.isadditive.aspx


[解决办法]
我6楼的回复应该错了。那里的“无效”好像不能直接当成是“false”。

我的理解是,只有“From”或“To”或“By”属性,这个动画是不是“不完整”的,既然不完整,那是不是动画的值就没有“锁住”目标的值呢?
[解决办法]
有这时间去看下源码就知道了。。。

 protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock)
    {
        if (!this._isAnimationFunctionValid)
        {
            this.ValidateAnimationFunction();
        }
        double normalizedTime = animationClock.CurrentProgress.Value;
        IEasingFunction easingFunction = this.EasingFunction;


        if (easingFunction != null)
        {
            normalizedTime = easingFunction.Ease(normalizedTime);
        }
        double num2 = 0.0;
        double num = 0.0;
        double num6 = 0.0;
        double num3 = 0.0;
        bool flag = false;
        bool flag2 = false;
        switch (this._animationType)
        {
            case AnimationType.Automatic:
                num2 = defaultOriginValue;
                num = defaultDestinationValue;
                flag = true;
                flag2 = true;
                break;

            case AnimationType.From:
                num2 = this._keyValues[0];
                num = defaultDestinationValue;
                flag2 = true;
                break;

            case AnimationType.To:
                num2 = defaultOriginValue;
                num = this._keyValues[0];
                flag = true;
                break;

            case AnimationType.By:


                num = this._keyValues[0];
                num3 = defaultOriginValue;
                flag = true;
                break;

            case AnimationType.FromTo:
                num2 = this._keyValues[0];
                num = this._keyValues[1];
                if (this.IsAdditive)
                {
                    num3 = defaultOriginValue;
                    flag = true;
                }
                break;

            case AnimationType.FromBy:
                num2 = this._keyValues[0];
                num = AnimatedTypeHelpers.AddDouble(this._keyValues[0], this._keyValues[1]);
                if (this.IsAdditive)
                {
                    num3 = defaultOriginValue;
                    flag = true;
                }
                break;
        }
        if (flag && !AnimatedTypeHelpers.IsValidAnimationValueDouble(defaultOriginValue))


        {
            throw new InvalidOperationException(SR.Get("Animation_Invalid_DefaultValue", new object[] { base.GetType(), "origin", defaultOriginValue.ToString(CultureInfo.InvariantCulture) }));
        }
        if (flag2 && !AnimatedTypeHelpers.IsValidAnimationValueDouble(defaultDestinationValue))
        {
            throw new InvalidOperationException(SR.Get("Animation_Invalid_DefaultValue", new object[] { base.GetType(), "destination", defaultDestinationValue.ToString(CultureInfo.InvariantCulture) }));
        }
        if (this.IsCumulative)
        {
            int? nullable2 = animationClock.CurrentIteration - 1;
            double factor = (double) nullable2.Value;
            if (factor > 0.0)
            {
                num6 = AnimatedTypeHelpers.ScaleDouble(AnimatedTypeHelpers.SubtractDouble(num, num2), factor);
            }
        }
        return AnimatedTypeHelpers.AddDouble(num3, AnimatedTypeHelpers.AddDouble(num6, AnimatedTypeHelpers.InterpolateDouble(num2, num, normalizedTime)));
    }


[解决办法]
只有在AnimationType.FromTo 或者AnimationType.FromBy的时候,IsAdditive才会做判断
[解决办法]
楼主在问第二段代码的问题,第一段代码没什么异议。

KumaPower, 你给出的是MSDN的IsAdditive的使用规则,但并不能解释第二段代码的疑问。楼主的使用方法没错。

ariesget,你从源代码层面解释的IsAdditive的使用规则,即如果动画仅设置了其 From、To 或 By 属性之一,则设置此属性将无效。跟楼主第二段代码中的问题也没有什么关系。楼主使用的规则也是正确的,没什么问题。
[解决办法]
没仔细看问题,第2个的话,因为你IsAdditive为True的时候,你的宽度是从你设置的Button的宽度+上From的值到+上To的值。表现就是300+75到300+130的动画。默认的FillBehavior是HoldEnd,也就是说,动画结束后会保持300+130的宽度。你可以把FillBehavior设置为Stop看下,动画结束后就会回到设置的值。


[解决办法]


[解决办法]
引用:
没仔细看问题,第2个的话,因为你IsAdditive为True的时候,你的宽度是从你设置的Button的宽度+上From的值到+上To的值。表现就是300+75到300+130的动画。默认的FillBehavior是HoldEnd,也就是说,动画结束后会保持300+130的宽度。你可以把FillBehavior设置为Stop看下,动画结束后就会回到设置的值。


FillBehavior 设置成stop当然可以了。你说都是正常的情况。
试想一下,就像你说的。刚开始的时候,button.width 是50,而且默认FillBehavior是HoldEnd。这时,宽度会从50 +75变化到50+130,也就是最后width是180,而且再强调一下,这时FillBehavior仍然是HoldEnd。所以你现在再做button1.Width = 300;本应该UI上的Button的Width是不会改变的。但事实是改变了。这就是问题所在。

14楼,你也看一下。先搞明白问题在哪里。
[解决办法]
引用:
Quote: 引用:

没仔细看问题,第2个的话,因为你IsAdditive为True的时候,你的宽度是从你设置的Button的宽度+上From的值到+上To的值。表现就是300+75到300+130的动画。默认的FillBehavior是HoldEnd,也就是说,动画结束后会保持300+130的宽度。你可以把FillBehavior设置为Stop看下,动画结束后就会回到设置的值。


FillBehavior 设置成stop当然可以了。你说都是正常的情况。
试想一下,就像你说的。刚开始的时候,button.width 是50,而且默认FillBehavior是HoldEnd。这时,宽度会从50 +75变化到50+130,也就是最后width是180,而且再强调一下,这时FillBehavior仍然是HoldEnd。所以你现在再做button1.Width = 300;本应该UI上的Button的Width是不会改变的。但事实是改变了。这就是问题所在。

14楼,你也看一下。先搞明白问题在哪里。

为什么要不变呢?
所谓HoldEnd跟Stop,只是把原始的值做了一个备份。当Stop的时候就把Width设置回原始值,HoldEnd的时候就用不做这步。这时候你再设置Button1的值跟动画没关系啊。只是正常的设置而已。
[解决办法]
引用:
Quote: 引用:

Quote: 引用:

没仔细看问题,第2个的话,因为你IsAdditive为True的时候,你的宽度是从你设置的Button的宽度+上From的值到+上To的值。表现就是300+75到300+130的动画。默认的FillBehavior是HoldEnd,也就是说,动画结束后会保持300+130的宽度。你可以把FillBehavior设置为Stop看下,动画结束后就会回到设置的值。


FillBehavior 设置成stop当然可以了。你说都是正常的情况。
试想一下,就像你说的。刚开始的时候,button.width 是50,而且默认FillBehavior是HoldEnd。这时,宽度会从50 +75变化到50+130,也就是最后width是180,而且再强调一下,这时FillBehavior仍然是HoldEnd。所以你现在再做button1.Width = 300;本应该UI上的Button的Width是不会改变的。但事实是改变了。这就是问题所在。

14楼,你也看一下。先搞明白问题在哪里。

为什么要不变呢?
所谓HoldEnd跟Stop,只是把原始的值做了一个备份。当Stop的时候就把Width设置回原始值,HoldEnd的时候就用不做这步。这时候你再设置Button1的值跟动画没关系啊。只是正常的设置而已。

测试了下,确实有点不正常,现象跟你前面说的一样。
------解决方案--------------------


请问按照楼主第二部分的代码:
请问按照楼主第二部分的代码:

DoubleAnimation widthAnimation = new DoubleAnimation();
widthAnimation.From = 75;
widthAnimation.To = 130;
widthAnimation.Duration = TimeSpan.FromSeconds(0.5);
widthAnimation.IsAdditive = true;
button1.BeginAnimation(Button.WidthProperty, widthAnimation);
button1.Width = 300;

正常的现象应该是什么?

从楼主的发帖就能看出来,正常的话:
button1.Width = 300; 这个设置不应该在UI上体现出来。
[解决办法]
回家做了点测试。由于没找到这部分执行的源码,只能靠测试结果猜测下。。。首先是当IsAdditive设置为true的时候,第一次执行完动画,width变为width + to的值,此时改变width属性,width变为改变后的width + to的值。然后第2次执行后,再改变width的值,没有效果,也就是被holdend的效果了。那么可以猜测,holdend他保存的是动画的参数to的值,而设置了IsAdditive后他在目标属性上的体现会是一个原始值 + to的值。第一次执行的时候,改原始值就是设置的width属性,所以此时修改width属性,会通知到视觉树上改变属性值,而之后对该属性值的其他设置为IsAdditive的动画,则跟width属性没有关系,width属性被存为一个备份,之后该属性值的设置为IsAdditive的动画都已前一个动画结束后的值为原始值,每次结束后依旧是原始值 + to的值。所以从第2个对该属性的动画开始,设置该属性不会影响到最后holdend的值了,只是修改了备份值。
[解决办法]
引用:
所谓HoldEnd跟Stop,只是把原始的值做了一个备份。当Stop的时候就把Width设置回原始值,HoldEnd的时候就用不做这步。这时候你再设置Button1的值跟动画没关系啊。只是正常的设置而已。


动画并不改变Width值。

反过来说,你以为控件的当前显示宽度是Width决定的?这是错误的。Width只是表示你设置的一个模型(理想)值,当前控件真正的宽度并不是Width决定的。



动画过程中根本不设置Width值,控件的可见宽度根本不必等于Width。除非当Stop以后。
[解决办法]

引用:
Quote: 引用:

所谓HoldEnd跟Stop,只是把原始的值做了一个备份。当Stop的时候就把Width设置回原始值,HoldEnd的时候就用不做这步。这时候你再设置Button1的值跟动画没关系啊。只是正常的设置而已。


动画并不改变Width值。

反过来说,你以为控件的当前显示宽度是Width决定的?这是错误的。Width只是表示你设置的一个模型(理想)值,当前控件真正的宽度并不是Width决定的。

动画过程中根本不设置Width值,控件的可见宽度根本不必等于Width。除非当Stop以后。

恩。动画过程中应该是这样吧。不过这个过程中跟这个问题关系不大貌似。主要是动画结束后,HoldEnd的情况下,如果是IsAdditive=true并且是第一次执行完动画后,修改Width的值会直接影响UI上显示的宽度为修改后的Width+To的值,然后之后运行后再修改都不会影响。所以我有#20的猜测。反编译查源码实在是找不到这块的实现,太大了...
[解决办法]
引用:
从楼主的发帖就能看出来,正常的话:
button1.Width = 300; 这个设置不应该在UI上体现出来。


怎么我反而觉得这个设置是应该在UI上呈现呢。。。
我换个写法写楼主的代码:

        DoubleAnimation widthAnimation = new DoubleAnimation();

        public MainWindow()
        {
            InitializeComponent();

            widthAnimation.Completed += new EventHandler(widthAnimation_Completed);
            widthAnimation.From = 75;
            widthAnimation.To = 130;
            widthAnimation.Duration = TimeSpan.FromSeconds(0.5);

            //条件1
            //widthAnimation.IsAdditive = true;

            
             widthAnimation.FillBehavior = FillBehavior.HoldEnd;
            //widthAnimation.FillBehavior = FillBehavior.Stop;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            button1.BeginAnimation(Button.WidthProperty, widthAnimation);
        }



        void widthAnimation_Completed(object sender, EventArgs e)
        {
            //条件2
            //button1.BeginAnimation(Button.WidthProperty, null);

            button1.Width = 300;
            MessageBox.Show(button1.Width.ToString());
        }



条件1:获取或设置一个值,该值指示是否应将目标属性的当前值与此动画的起始值相加。
条件2:移除动画。

情况1(widthAnimation.IsAdditive = false;动画不移除):
结果:130。我的理解:主要原因是动画没有移除,DoubleAnimation仍然重写着Button的Width值。
-----------------------------------------------情况2(widthAnimation.IsAdditive = false;动画移除):
结果:300。我的理解:主要原因是动画移除了,DoubleAnimation没有影响到Width值了,所以当前值会更改成300。
-----------------------------------------------情况3(widthAnimation.IsAdditive = true;动画不移除)[楼主的第二部分]:
结果:430(130+300)。虽然动画没有移除,但IsAdditive设为true,造成DoubleAnimation没有重写Width值,而且能与目标属性“互动”。
----------------------------------------------
情况3(widthAnimation.IsAdditive = true;动画移除):
结果:300。原因与情况2相当。

==================================================================================
我觉得问题的原因是:button1.Width = 300之前,动画是否移除,IsAdditive属性的是否造成DoubleAnimation重写Width值。

FillBehavior.Stop的设置是告诉动画结束不再影响Width值,而FillBehavior.HoldEnd是会影响Width值,但它不是负责重写Width。

热点排行