2008-11-13 15 views
8

Ich versuche, eine einfache WPF-Anwendung anzupassen, um das Model-View-ViewModel-Muster zu verwenden. Auf meiner Seite habe ich ein paar Animationen:Verwenden der Datenbindung zum Starten von Animationen in WPF

<Page.Resources> 
    <Storyboard x:Name="storyboardRight" 
       x:Key="storyboardRight"> 
     <DoubleAnimation x:Name="da3" 
         Storyboard.TargetName="labelRight" 
         Storyboard.TargetProperty="Opacity" 
         From="0" 
         To="1" 
         Duration="0:0:0.5" /> 
     <DoubleAnimation x:Name="da4" 
         Storyboard.TargetName="labelRight" 
         Storyboard.TargetProperty="Opacity" 
         From="1" 
         To="0" 
         BeginTime="0:0:1" 
         Duration="0:0:0.5" /> 
    </Storyboard> 
    ... 
</Page.Resources> 

Zur Zeit beginne ich die Animation in der Code-behind, und kann auf das Completed-Ereignis zu hören, etwas zu tun, wenn es mit dem folgenden Code beendet:

storyboardRight = (Storyboard)TryFindResource("storyboardRight"); 
storyboardRight.Completed += new EventHandler(storyboardRight_Completed); 
storyboardRight.Begin(this); 

Gibt es eine Möglichkeit, das Storyboard an mein ViewModel zu binden, sodass es bei einem vom ViewModel aufgerufenen Ereignis startet und nach Abschluss des ViewModel erneut aufgerufen werden kann?

Antwort

9

Ich hatte die Gelegenheit, diese Frage an Microsofts Josh Twist zu stellen, der sich freundlicherweise die Zeit genommen hat, eine Antwort auf dieses Problem zu geben. Die Lösung besteht darin, eine DataTrigger in Kombination mit einer Enumeration im ViewModel zu verwenden, um das Storyboard zu starten, und dies wiederum erfordert das Einfügen der Seite in eine ContentPresenter. Um mit der Beendigung der Animation fertig zu werden, war eine kleine Menge Code erforderlich, um einen Anruf in ein ICommand auf dem ViewModel zu tätigen.

Lesen Sie Joshs Beitrag here für eine vollständige Beschreibung der Lösung.

+0

Diese Lösung erfordert nur das Einfügen der Seite in einen CpntentPresenter, wenn Sie ein DataTemplate. Es ist möglich, sie in den Triggern eines Steuerelementstils anstelle der Trigger des DataTemplate zu verwenden, wenn Sie die Eigenschaften des Steuerelements animieren. –

+0

Der Link zu Josh Twists Website ist defekt. Anscheinend ist Joshs gesamte Seite kaputt (keine Blog-Artikel geladen) und wenn ich versuche, ihm eine E-Mail zu schicken, springt es einfach ab. Wer weiß, wie man Josh kontaktiert und die Situation behebt? –

+0

@SimonGillbee Ich habe ihm eine Nachricht auf Twitter gesendet –

1

Sie müssen eine EventTrigger verwenden. Diese article about Animations in WPF könnte helfen. Siehe auch die Routed Events Overview auf der MSDN und How to: Use Event Triggers to Control a Storyboard After It Starts.

+0

danke für Der Zeiger, aber alle Dokumente für EventTrigger zeigen an, dass er durch ein Ereignis ausgelöst wird, das von einem vorhandenen FrameworkElement kommt. Ich feuere jetzt ein RoutedEvent von meinem ViewModel ab, kann aber nicht sehen, wie ich das XAML zum Abonnieren bekomme:

1

Ich tat dies durch eine Verwendung von DataTrigger und binden es an eine Eigenschaft in meinem ViewModel. Wenn die "FlashingBackGround" -Eigenschaft auf "ON" gesetzt wird, startet die Storyboard-Animation.

Vergewissern Sie sich auch in Ihrem Projekt einen Verweis auf "Microsoft.Expression.Interactions"

XAML: (dies geht direkt in den Wurzelknoten)

<Window 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
    x:Name="window" > 
    ... 

    <i:Interaction.Triggers> 
     <ei:DataTrigger Binding="{Binding FlashingBackground, Mode=OneWay}" Value="ON"> 
     <ei:ControlStoryboardAction Storyboard="{StaticResource MyAnimation}"  
               ControlStoryboardOption="Play"/> 
     </ei:DataTrigger> 
    </i:Interaction.Triggers> 

    ... 
</Window> 

Ansichtsmodell:

private void TurnOnFlashingBackround() 
    { 
     this.FlashingBackground = "ON"; 
    } 

    private string _FlashingBackround = "OFF"; 

    public string FlashingBackground 
    { 
     get { return this._FlashingBackround; } 

     private set 
     { 
      if (this.FlashingBackground == value) 
      { 
       return; 
      } 

      this._FlashingBackround = value; 
      this.OnPropertyChanged("FlashingBackground"); 
     } 
    } 

    public new event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged(
       this, 
       new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

Schließlich muss das Viewmodel von "INotifyPropertyChanged" erben

+0

Beachten Sie auch: Sie benötigen zwei Assembly Referenzen: System.Windows.Interactivity und die oben genannten Microsoft.Expression.Interactions. – eFloh