在做動畫的時候如果使用自訂的相依性屬性來綁定動畫,將會使我們軟體的整體架構得到很大的提升,實現動畫與頁面邏輯的分離。
在wp7上我們能很輕鬆的實現這個效果。
假如我們需要介面上的一個按鈕做運動。
xaml:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Button Name="btnAnimal" Content="Button" VerticalAlignment="Top" Click="Button_Click_1"/> </Grid>
後台:
SlideTranslate slide = new SlideTranslate(); slide.Add(btnAnimal); DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 700, Duration = new Duration(TimeSpan.FromMilliseconds(1000)) }; Storyboard.SetTarget(animation, slide); Storyboard.SetTargetProperty(animation, new PropertyPath("SlideTranslate.Y")); Storyboard sb = new Storyboard(); sb.Children.Add(animation); sb.Begin();
SlideTranslate:動畫類。
public class SlideTranslate : DependencyObject { public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double), typeof(SlideTranslate), new PropertyMetadata(-1.0, OnTransitionChanged)); public static bool IsAnimal = false; public double Y { set { SetValue(YProperty, value); } get { return (double)GetValue(YProperty); } } static void OnTransitionChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { (obj as SlideTranslate).OnTransitionChanged(args); } public FrameworkElement Element { get; set; } TranslateTransform t = new TranslateTransform(); public void Add(FrameworkElement element) { element.RenderTransform = t; this.Element = element; } void OnTransitionChanged(DependencyPropertyChangedEventArgs args) { t.Y = Y; } }
這樣,我們就實現了動畫與邏輯的分離。我們的後台代碼不需要實現它做什麼運動,只需要把那個相依性屬性綁到動畫上就可以了。
至於你做什麼動畫是由SlideTranslate它來決定的 。如果我們將OnTransitionChanged裡面的方法改成t.X=Y;那麼就是x橫向的運動了。
這樣我們就能藉助一些介面抽象類別等實現各種各樣的效果,而且在架構上得到很大的提升。
但是到win8 的時候我們會發現這個方式根本行不通,因為會報錯。
當然我們要把代碼稍作更改
Storyboard.SetTargetProperty(animation, new PropertyPath("SlideTranslate.Y"));
改成Storyboard.SetTargetProperty(animation, "SlideTranslate.Y");
這樣會發現報這個錯誤。
這裡就關係到了一個 XamlTypeInfo 的內容,因為你的動畫是通過代碼添加的, 所以在反射這個屬性的時候,他需要在XamlTypeInfo中尋找這個SlideTranslate的內容,以及他的屬性列表。 但是它沒有找到,因為VS沒有為SlideTranslate在XamlTypeInfo中產生相應的資訊。如果你在XAML只要添加過一次 <local:SlideTranslate.../> VS就會產生此資訊,你的動畫就可以運行了。 當然這個解決辦法你可以在XAML建立一個隱藏的SlideTranslate, 或者定義其為一個資源。
也就是說我們需要在xaml對SlideTranslate進行聲明。
<Page.Resources> <local:SlideTranslate x:Key="trans"></local:SlideTranslate> </Page.Resources>
這樣雖然不報錯了,但是動畫依然不執行 ,調試發現,OnTransitionChanged這個事件根本沒被觸發,也就是說屬性Y的值沒有發生變化。
不廢話了,其實我們少了一個動畫屬性的設定。
anima.EnableDependentAnimation = true;
那麼最後完整的代碼如下
SlideTranslate slide = new SlideTranslate();
slide.Add(btnAnimal);
DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 700, Duration = new Duration(TimeSpan.FromMilliseconds(1000)) };
animation.EnableDependentAnimation = true;
Storyboard.SetTarget(animation, slide);
Storyboard.SetTargetProperty(animation, "(SlideTranslate.Y)");
Storyboard sb = new Storyboard();
sb.Children.Add(animation);
sb.Begin();