2012-10-15 83 views
7

基本上,我想製作一些形狀並使它們變成動畫。於是我想出了以下自定義類:Windows 8 - 動畫代碼隱藏的自定義屬性

public class FunkyShape : DependencyObject 
{ 
    public double Animator 
    { 
     get { return (double)GetValue(AnimatorProperty); } 
     set { SetValue(AnimatorProperty, value); } 
    } 

    public static readonly DependencyProperty AnimatorProperty = 
     DependencyProperty.Register("Animator", typeof(double), typeof(FunkyShape), 
     new PropertyMetadata(0, new PropertyChangedCallback(Animator_Changed))); 

    private static void Animator_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     double delta = (double)e.NewValue - (double)e.OldValue; 

     ((FunkyShape)d).ProcessDelta((double)e.NewValue, delta); 
    } 

    private void ProcessDelta(double val, double delta) 
    { 
     Holder.Width = val; 
     Holder.Height = val; 

     // Keep shape centered 
     HolderPosition.X = delta/2; 
     HolderPosition.Y = delta/2; 
    } 

    private Shape Holder; 
    public TranslateTransform HolderPosition 
    { 
     get { return (TranslateTransform)Holder.RenderTransform; } 
    } 


    public FunkyShape(Canvas playground, Shape shapeToInit) 
    { 
     Holder = shapeToInit; 

     Holder.Width = 10; 
     Holder.Height = 10; 
     Holder.Fill = new SolidColorBrush(Colors.Blue); 
     Holder.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Center; 
     Holder.RenderTransform = new TranslateTransform() 
     { 
      X = 500, 
      Y = 500 
     }; 
     Holder.RenderTransformOrigin = new Point(0.5, 0.5); 

     // init done 
     playground.Children.Add(Holder); 

     Animate(); 
    } 

    public void Animate() 
    { 
     DoubleAnimation g1 = GrowAnimation(); 

     Storyboard sb = new Storyboard(); 
     Storyboard.SetTarget(g1, this); 

     // CAN'T FIND ANIMATOR PROPERTY 
     Storyboard.SetTargetProperty(g1, "Animator"); 

     sb.Children.Add(g1); 

     sb.Begin(); // THROWS EXCEPTION 
    } 

    private static DoubleAnimation GrowAnimation() 
    { 
     DoubleAnimation growAnimation = new DoubleAnimation(); 
     growAnimation.Duration = TimeSpan.FromMilliseconds(3000); 
     growAnimation.From = 0; 
     growAnimation.To = 100; 
     growAnimation.AutoReverse = true; 
     growAnimation.EnableDependentAnimation = true; 
     growAnimation.RepeatBehavior = new RepeatBehavior(5); 
     return growAnimation; 
    } 
} 

然而,當我嘗試使類的一個實例,並將其添加到畫布上,我得到異常 - Storyboard.Being()拋出它,並告訴我,它找不到Animator屬性。

所以 - 我做錯了什麼?

編輯: 3代碼更改後 - 它仍然不工作;我得到「無法解析指定對象上的TargetProperty Animator」錯誤。所以如果有人知道答案 - 請通過修改代碼來幫忙。謝謝!

編輯: OK 24小時撞頭撞牆後有一些進步 - 如果我添加形狀通過XAML是動畫,但如果我添加它通過代碼背後(Canvas.Children.Add),它不起作用。讓我看看我能弄清楚爲什麼。

+0

這就是我面臨的問題。如果你找到一個解決方案,請在這裏發佈,所以我會;) –

+1

我認爲這是相關的:http://www.charlespetzold.com/blog/2012/03/The-Animated-Pie-Slice-in- Windows-8.html – kape123

+0

那麼,這篇文章是關於這一個http://blog.jerrynixon.com/2012/06/windows-8-animated-pie-slice.html –

回答

6

OK,

我發現什麼明顯的是框架內的一個錯誤(雖然我敢肯定,一些MS員工將發佈響應,並說這是一個功能/它 - 是 - 解決方法通過設計)。有幾件事情需要做:

  1. 添加默認/無參數的構造函數
  2. 更改基類FunkyShape到用戶控件。
  3. 打開要添加形狀
  4. 添加FunkyShape的一個實例作爲畫布XAML中的孩子Page類的XAML視圖(< TM:FunkyShape/>爲例)。 它不會與此無關。
  5. 在代碼隱藏中創建一個FunkyShape實例,將其添加到畫布中,啓動動畫並欣賞它的工作原理
  6. 切換到較少bug的技術。
+0

非常感謝,這對我來說! – thumbmunkeys

+0

在XAML中添加實例確實爲我解決了問題;謝謝你的提示。但不幸的是,對我來說這不是一個可行的解決方案,因爲我真的不想在我的類上使用無參數的構造函數(這沒有任何意義)。我懷疑它是有效的,因爲XAML編譯器生成一些關於XAML中使用的類型的元數據,故事板需要這些元數據。如果我找到更好的解決方法,我會讓你知道。 –

+0

步驟4可能與Tim Heuer的回覆有關https://social.msdn.microsoft.com/Forums/windowsapps/en-US/5e42e6a1-740f-48b2-9908-09a474f9d413/error-converter-failed-to-convert-值的型時型是衍生?論壇= winappswithcsharp –

1

是的,您必須將此屬性定義爲依賴項屬性,而不僅僅是一個常規的CLR屬性。這涉及到很多簡單的鍋爐板代碼。因此,請參閱博客文章一個完整的例子:

http://timheuer.com/blog/archive/2012/03/07/creating-custom-controls-for-metro-style-apps.aspx

+0

我剛剛嘗試將其註冊爲DependencyProperty(更新後的代碼),並且我得到相同的錯誤 – kape123

+0

您的屬性路徑錯誤,您的目標對象是'FunkyShape',如此語句中指定'Storyboard.SetTarget(g1,this); '所以你的目標屬性應該是'Animator','Storyboard.SetTargetProperty(g1,「Animator」);' - 另外,你需要添加一個處理程序到DependencyProperty改變的事件,以便更新你的UI,因爲依賴屬性是動畫。 – ColinE

+0

@ColinE:動畫不會調用屬性的setter,對吧?但它會調用一個PropertyChangedCallback? –

3

在Windows 8中,你不能沒有enabledependentanimation屬性也設置爲true,動畫自定義屬性。這是因爲默認情況下禁用了非確定性動畫。

Reference: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.animation.pointanimation.enabledependentanimation.aspx

+1

正如聊天上說的,我確實有 - growAnimation.EnableDependentAnimation = true; - 線,所以不是這樣。 – kape123

+1

非常感謝,它解決了我的問題:) –

+0

@FlorianGl你可以發佈你的課程嗎?因爲這顯然不適合我的? – kape123

1

好的,我也有這個問題,但我不想在我的類中包含一個公共無參數構造函數,所以我找到了另一種方法。

基本上,問題是WinRT是一個本地平臺,它不能對.NET代碼進行反思。這就是爲什麼WinRT應用程序的構建過程會生成有關XAML中所用類型的元數據(可在obj/(Debug|Release)/XamlTypeInfo.g.cs中找到相關代碼)。

如果在XAML中永遠不會使用類型,則不會生成有關此類型的元數據,這意味着(除其他之外)不能爲此類型的屬性設置動畫。

如果你正在編寫一個類庫,你可以只包含一個XAML資源字典並聲明一個類型的虛擬實例;它會導致生成元數據。但是,它要求該類型具有一個公共無參數的構造函數,這可能不合意。

所以還有另一種解決方案:自己提供元數據。有幾個接口可以實現,而且它們有很多成員,所以手動操作可能非常繁瑣。幸運的是,你不必!這裏是你可以做什麼:

  • 在裏面添加一個公共的無參數的構造函數的類(臨時)
  • 創建XAML ResourceDictionary,並宣佈一個實例類(如上所述)
  • 複製XamlTypeInfo.g.cs文件到您的項目(我把它改名爲XamlTypeInfo.cs
  • 更換調用構造函數throw new NotImplementedException()
  • 刪除ResourceDictionary文件
  • 刪除公共無參數構造函數

而你完成了,動畫現在可以正常工作。

的過程還是相當繁瑣,所以這將是很好有一個工具來爲我們做的工作......


編輯:簡單的解決方案:應用[Bindable]屬性的類。它使得元數據生成器即使未在XAML中使用,也會考慮類型。 (忽略文檔說這是針對C++類型的事實;它在C#類中也能很好地工作)