0

コントロールが最小限の時間、特定の状態のままであることを確認したいと考えています。コントロールには と の 2 つの状態がLoadingありLoadedます。Loading状態はアニメーションを表示し、状態Loadedはデータを表示します。2 つの状態の間にフェードイン/フェードアウト遷移があります。

ただし、問題は、データの読み込みが速すぎて、アニメーションが画面上で一瞬フリックアップし、すぐにフェードアウトする場合があることです。これは見栄えが悪いので、私がやりたいことは、Loading状態で費やされる最小時間 (0.5 秒など) を強制することです。そうすれば、データがすばやく読み込まれる場合でも、読み込みアニメーションは少なくとも十分長く表示されるので、不快な効果はありません。

私は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 に答える