0

我想确保控件在最短的时间内保持某种状态。该控件有两种状态:LoadingLoadedLoading状态显示动画,状态Loaded显示数据。两种状态之间存在淡入/淡出过渡。

但是,问题有时是数据加载速度过快,以至于动画在屏幕上瞬间闪烁,然后立即淡出。Loading这看起来很糟糕,所以我想做的是强制在该州花费最少的时间(例如半秒) 。这样,即使数据加载速度很快,加载动画至少会显示足够长的时间而不会产生不和谐的效果。

我已经设法通过VisualStateManager我想象中称为的自定义来实现这一点MinimumTimeVisualStateManager。但是,我想知道是否有一种内置方法可以在不需要这些额外代码的情况下实现我想要的。

谢谢

4

1 回答 1

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>

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

肯特

于 2010-07-17T11:44:55.673 回答