2010-07-17 8 views
0

Je veux m'assurer qu'un contrôle reste dans un certain état pendant un minimum de temps. Le contrôle a deux états: Loading et Loaded. L'état Loading affiche une animation et l'état Loaded affiche les données. Il y a une transition de fondu entrant/sortant entre les deux états.Imposer des durées minimales dans un état visuel donné

Cependant, le problème est parfois que les données se chargent si rapidement que l'animation se déclenche momentanément sur l'écran puis disparaît immédiatement. Cela semble médiocre, donc ce que je veux faire est d'imposer un minimum de temps (par exemple une demi-seconde) passé dans l'état Loading. De cette façon, même si les données se chargent rapidement, l'animation de chargement s'affichera au moins assez longtemps pour ne pas avoir d'effet discordant.

J'ai réussi à atteindre cet objectif avec un VisualStateManager personnalisé que j'appelais MinimumTimeVisualStateManager. Cependant, je me demande s'il existe un moyen intégré de réaliser ce que je veux sans avoir besoin de ce code supplémentaire.

Merci

Répondre

1

Voici ma solution:

// a VisualStateManager that can impose minimum times that a control is in a particular state 
public class MinimumTimeVisualStateManager : VisualStateManager 
{ 
    public static readonly DependencyProperty MinimumTimeProperty = DependencyProperty.RegisterAttached("MinimumTime", 
     typeof(TimeSpan), 
     typeof(MinimumTimeVisualStateManager), 
     new PropertyMetadata(TimeSpan.Zero)); 

    private static readonly DependencyProperty StateChangeMinimumTimeProperty = DependencyProperty.RegisterAttached("StateChangeMinimumTime", 
     typeof(DateTime), 
     typeof(MinimumTimeVisualStateManager), 
     new PropertyMetadata(DateTime.MinValue)); 

    public static TimeSpan GetMinimumTime(VisualState visualState) 
    { 
     visualState.AssertNotNull("visualState"); 
     return (TimeSpan)visualState.GetValue(MinimumTimeProperty); 
    } 

    public static void SetMinimumTime(VisualState visualState, TimeSpan minimumTime) 
    { 
     visualState.AssertNotNull("visualState"); 
     visualState.SetValue(MinimumTimeProperty, minimumTime); 
    } 

    private static DateTime GetStateChangeMinimumTime(Control control) 
    { 
     control.AssertNotNull("control"); 
     return (DateTime)control.GetValue(StateChangeMinimumTimeProperty); 
    } 

    private static void SetStateChangeMinimumTime(Control control, DateTime stateChangeMinimumTime) 
    { 
     control.AssertNotNull("control"); 
     control.SetValue(StateChangeMinimumTimeProperty, stateChangeMinimumTime); 
    } 

    protected override bool GoToStateCore(Control control, FrameworkElement templateRoot, string stateName, VisualStateGroup group, VisualState state, bool useTransitions) 
    { 
     var minimumTimeToStateChange = GetStateChangeMinimumTime(control); 

     if (DateTime.UtcNow < minimumTimeToStateChange) 
     { 
      // can't transition yet so reschedule for later 
      var dispatcherTimer = new DispatcherTimer(); 
      dispatcherTimer.Interval = minimumTimeToStateChange - DateTime.UtcNow; 
      dispatcherTimer.Tick += delegate 
      { 
       dispatcherTimer.Stop(); 
       this.DoStateChange(control, templateRoot, stateName, group, state, useTransitions); 
      }; 
      dispatcherTimer.Start(); 

      return false; 
     } 

     return this.DoStateChange(control, templateRoot, stateName, group, state, useTransitions); 
    } 

    private bool DoStateChange(Control control, FrameworkElement templateRoot, string stateName, VisualStateGroup group, VisualState state, bool useTransitions) 
    { 
     var succeeded = base.GoToStateCore(control, templateRoot, stateName, group, state, useTransitions); 

     if (succeeded) 
     { 
      SetStateChangeMinimumTime(control, DateTime.MinValue); 
      var minimumTimeInState = GetMinimumTime(state); 

      if (minimumTimeInState > TimeSpan.Zero) 
      { 
       SetStateChangeMinimumTime(control, DateTime.UtcNow + minimumTimeInState); 
      } 
     } 

     return succeeded; 
    } 
} 

et il est utilisé comme ceci:

<VisualStateManager.VisualStateGroups> 
    <VisualStateGroup x:Name="Modes"> 
     <VisualState x:Name="Loading" local:MinimumTimeVisualStateManager.MinimumTime="0:00:0.5"/> 

     <VisualState x:Name="Loaded"> 
      <Storyboard> 
       <!-- omitted for clarity --> 
      </Storyboard> 
     </VisualState> 
    </VisualStateGroup> 
</VisualStateManager.VisualStateGroups> 

Il semble fonctionner très bien, mais espère que c'est le code que je peux supprimer .

Kent

Questions connexes