在執行期動態的改變Grid容器中某個Row或是Column大小的功能應該是個蠻常見的情況,但是有時候我們希望由程式來調整Row的高度或是Column的寬度時,可以很輕鬆的透過程式來解決,但是,如果在改變的時候,要套用動畫呢??
在執行期動態的改變Grid容器中某個Row或是Column大小的功能應該是個蠻常見的情況,但是有時候我們希望由程式來調整Row的高度或是Column的寬度時,可以很輕鬆的透過程式來解決,但是,如果在改變的時候,要套用動畫呢??
Grid的分割單位使用的是GridLength,並不是Double,所以沒辦法直接套用DoubleAnimation,這時候怎麼辦呢?還好WPF可以讓我們繼承AnimationTimeline來實作自己的新動畫,所以我們就自己來打造一個GridLengthAnimation的新動畫類別吧!!
AnimationTimeline中有幾個重要的Property是和動畫息息相關的:
1. From屬性:GridLength的初始值
2. To屬性:GridLength的結束值
3. EasingFunction屬性:動畫都做了,不能套EasingFunction怎麼行呢!? (注意:IEasingFunction是.Net Framework4.0新增的介面)
4. TargetPropertyType:當然是GridLength囉
5. CurrentValue:會回傳0~1之間的double值,用來控制動畫撥放的動線。
有了以上的觀念,我們就可以動手啦!!剛剛前面說了,有三個屬性要做,所以我們必需註冊三個DependencyProperty,另外要override掉CreateInstanceCore()、GetCurrentValue()這兩個Function和TargetPropertyType這個Property。
廢話不多說,就直接把原始碼Po出來,請各位服用吧!!
using System;
using System.Windows;
using System.Windows.Media.Animation;
public class GridLengthAnimation : AnimationTimeline
{
public static readonly DependencyProperty FromProperty;
public static readonly DependencyProperty ToProperty;
public static readonly DependencyProperty EasingFunctionProperty;
static GridLengthAnimation()
{
FromProperty = DependencyProperty.Register( "From" , typeof( GridLength ) , typeof( GridLengthAnimation ) );
ToProperty = DependencyProperty.Register( "To" , typeof( GridLength ) , typeof( GridLengthAnimation ) );
EasingFunctionProperty = DependencyProperty.Register( "EasingFunction" , typeof( IEasingFunction ) , typeof( GridLengthAnimation ) );
}
protected override Freezable CreateInstanceCore()
{
return new GridLengthAnimation();
}
public override Type TargetPropertyType
{
get { return typeof( GridLength ); }
}
public IEasingFunction EasingFunction
{
get
{
return ( IEasingFunction ) GetValue( GridLengthAnimation.EasingFunctionProperty );
}
set
{
SetValue( GridLengthAnimation.EasingFunctionProperty , value );
}
}
public GridLength From
{
get
{
return ( GridLength ) GetValue( GridLengthAnimation.FromProperty );
}
set
{
SetValue( GridLengthAnimation.FromProperty , value );
}
}
public GridLength To
{
get
{
return ( GridLength ) GetValue( GridLengthAnimation.ToProperty );
}
set
{
SetValue( GridLengthAnimation.ToProperty , value );
}
}
public override object GetCurrentValue( object defaultOriginValue , object defaultDestinationValue , AnimationClock animationClock )
{
double fromValue = ( ( GridLength ) GetValue( GridLengthAnimation.FromProperty ) ).Value;
double toValue = ( ( GridLength ) GetValue( GridLengthAnimation.ToProperty ) ).Value;
IEasingFunction easingFunction = this.EasingFunction;
double progress = ( easingFunction != null ) ? easingFunction.Ease( animationClock.CurrentProgress.Value ) : animationClock.CurrentProgress.Value;
if( fromValue > toValue )
{
return new GridLength( ( 1 - progress ) * ( fromValue - toValue ) + toValue , this.To.IsStar ? GridUnitType.Star : GridUnitType.Pixel );
}
else
{
return new GridLength( ( progress ) * ( toValue - fromValue ) + fromValue , this.To.IsStar ? GridUnitType.Star : GridUnitType.Pixel );
}
}
}
至於使用方法呢?附上小小的範例給各位參考: