2010-07-17 32 views
0

我希望确保控件在特定状态下保持最短时间。该控件有两个状态:LoadingLoadedLoading状态显示动画,Loaded状态显示数据。这两种状态之间有淡入/淡出过渡。在给定的视觉状态下花费的最短时间

但是,问题是有时数据加载速度太快,以至于动画会瞬间在屏幕上弹起,然后立即淡出。这看起来很差,所以我想要在Loading状态下花费最少的时间(例如半秒)。这样,即使数据加载速度很快,加载动画至少会显示足够长的时间以避免产生震动效果。

我已经设法实现这个自定义VisualStateManager,我想象地叫MinimumTimeVisualStateManager。但是,我想知道是否有内置的方式来实现我想要的,而不需要额外的代码。

感谢

回答

1

这里是我的解决方案:

// 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; 
    } 
} 

而且它使用的是这样的:

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

这似乎工作得很好,但我希望这是代码,我可以删除。

肯特

相关问题