2010-03-28 4 views
7

J'écris une application MVVM et j'ai commencé à mettre quelques animations. Je veux appeler quelque chose sur le ViewModel qui démarre le storyboard. This blog had a promising approach to it, mais cela ne fonctionne pas réellement. Le gestionnaire IDChanged ne se déclenche jamais pour une raison quelconque.Démarrage d'une animation à partir de ViewModel dans WPF/MVVM

J'ai également trouvé que vous pouviez démarrer des animations sur EventTriggers, mais je ne sais pas comment en déclencher une sur le ViewModel.

Répondre

0

J'ai fini par ajouter un événement AnimationStarted à mon ViewModel avec une chaîne clé pour quelle animation il s'agit. Ensuite, dans la vue, je crée l'animation par programme, abonnez-vous à l'événement AnimationStarted et désactivez l'animation appropriée lorsqu'elle se déclenche.

1

J'ai une propriété dans ma machine virtuelle qui reflète l'état de l'application. Les éléments de la vue qui sont animés ont un déclencheur de données qui démarre un storyboard lorsque la propriété VM a une certaine valeur.

+0

Je sais comment faire. Vous définissez un déclencheur pour démarrer le storyboard lorsque vous entrez une condition. Mais j'ai juste besoin de faire une animation unique: je veux faire un flash rapide et temporaire sur un élément de l'interface utilisateur pour attirer l'attention. – RandomEngy

+0

Je n'ai pas envisagé de généraliser cela, donc je ne sais pas si cela vous aide. J'ai déjà eu un besoin similaire. Je devais 'clignoter' un bouton s'il n'y avait pas d'activité pendant une minute. Je l'ai fait en ayant un storyboard attaché au bouton, le storyboard ne ferait rien pendant une minute puis faire le flash. Dans mon cas, le bouton disparaissait lorsqu'on le cliquait, ce qui rendait le scénario plus simple. Un flash sur un élément d'interface utilisateur pour attirer l'attention ressemble à une vue uniquement liée. Y a-t-il une façon dont la vue peut déterminer quand à l'éclair par lui-même? Pourquoi la VM se soucierait-elle de faire clignoter un élément d'interface utilisateur? Désolé, cela peut ne pas être d'une grande aide. – Carlos

+0

Eh bien, plusieurs commandes qui se déclenchent sur une fenêtre déclencheraient ce flash dans une autre fenêtre. Mon modèle de fenêtrage est configuré de telle sorte que la VM connaisse les relations entre les fenêtres, mais pas les vues. – RandomEngy

5

Je l'ai fait en utilisant un DataTrigger et en le liant à une propriété dans mon ViewModel. Lorsque la propriété "FlashingBackGround" est définie sur "ON", l'animation Storyboard démarre.

Assurez-vous aussi d'inclure dans votre projet une référence à "Microsoft.Expression.Interactions"

XAML: (cela va directement dans le nœud racine)

<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> 

ViewModel:

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

    private string _FlashingBackround = "OFF"; 

    public string FlashingBackground 
    { 
     get { return _FlashingBackround; } 

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

      _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)); 
     } 
    } 

Enfin, le Viewmodel doit hériter de "INotifyPropertyChanged"

+6

Approche intéressante. Mais pourquoi ne pas simplement utiliser un 'boolean' au lieu d'une chaîne" ON "/" OFF "? –

+0

Assurez-vous d'ajouter le "System.Windows.Interactivity.dll" aussi. –

0

J'ai rencontré le même problème, et aucun de ces messages n'a vraiment aidé parce que les animations sont en code, et certaines d'entre elles étaient grandes et compliquées et nécessitaient des variables fluctuantes, donc elles devaient rester dans le code. Je l'ai résolu en ajoutant des propriétés de dépendance dans le contrôle utilisateur (vue) qui déclenchent les animations et en les liant aux propriétés du modèle de vue. Je ne sais pas (/ soin) si cela viole quelque chose ou autre, parce que cela fonctionne très bien! acclamations, Stepp

extrait:

(vue) Code Usercontrol derrière:

public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     SetAnimationBindings(); 
    } 

    private void SetAnimationBindings() 
    { 
     _dialogStartPosition = mbFolderBrowse.Margin; 

     var propName = "StartDialogAnimation"; 
     var binding = new Binding(propName) { Mode = BindingMode.TwoWay }; 
     this.SetBinding(DialogAnimationProperty, binding); 

     propName = "StartProgressAnimation"; 
     binding = new Binding(propName) { Mode = BindingMode.TwoWay }; 
     this.SetBinding(ProgressAnimationProperty, binding); 
    } 

    #region Animation Properties 
    #region DialogAnimation 
    public static readonly DependencyProperty DialogAnimationProperty = 
     DependencyProperty.Register("DialogAnimation", typeof(bool), 
      typeof(Manage), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDialogAnimationChanged)); 
    public bool DialogAnimation 
    { 

     get { return (bool)this.GetValue(DialogAnimationProperty); } 
     set 
     { 
      var oldValue = (bool)this.GetValue(DialogAnimationProperty); 
      if (oldValue != value) this.SetValue(DialogAnimationProperty, value); 
     } 
    } 

    private static void OnDialogAnimationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     Manage m = o as Manage; 

     if ((bool)e.NewValue == true) 
      m.SlideInDialogPanel(); // animations 
     else 
      m.SlideOutDialogPanel(); 
    } 
    #endregion 

View-Modèle:

public bool StartDialogAnimation 
{ 
    get { return _startDialogAnimation; } 
    set 
    { 
     if (_startDialogAnimation != value) 
     { 
      _startDialogAnimation = value; 
      RaisePropertyChanged("StartDialogAnimation"); 
     } 
    } 
} 
Questions connexes