WPF Animation запускается, но показывает слишком поздно - PullRequest
8 голосов
/ 26 мая 2011

Я создаю некоторые элементы управления WPF, используя .Net 4.0.Один из этих элементов управления, называемый LoadingPane, представляет собой пользовательский элемент управления, производный от ContentControl.Единственная задача этого элемента управления LoadingPane - показывать полупрозрачный слой поверх содержимого, если для свойства IsLoading установлено значение true.Я использую некоторые анимации для постепенного исчезновения при изменении значения IsLoading.Когда отображается наложение, анимация вращает круг эллипсов.

Пока все хорошо.Это все работает очень хорошо.Но вот моя проблема: когда я устанавливаю свойство Loading в true, анимация не отображается напрямую.Это займет около полсекунды.В это время анимация постепенного появления уже запущена, поэтому прозрачность фактически увеличивается от 0 до 1. За один шаг.

Вот мой код анимации:

<ControlTemplate.Triggers>
    <Trigger Property="IsLoading"
             Value="True">
        <Trigger.EnterActions>
            <RemoveStoryboard BeginStoryboardName="EndAnimateLoadingCanvas" />
            <BeginStoryboard Name="AnimateLoadingCanvas">
                <Storyboard FillBehavior="Stop">
                    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
                                                   Storyboard.TargetName="MyViewBoxje"
                                                   Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
                    </ObjectAnimationUsingKeyFrames>

                    <DoubleAnimation BeginTime="00:00:00"
                                     Duration="00:00:00.5"
                                     Storyboard.TargetName="MyViewBoxje"
                                     Storyboard.TargetProperty="Opacity"
                                     To="1" />

                    <DoubleAnimation BeginTime="00:00:00"
                                     Duration="00:00:02"
                                     Storyboard.TargetName="AnimatedRotateTransform"
                                     Storyboard.TargetProperty="Angle"
                                     From="360"
                                     To="0"
                                     RepeatBehavior="Forever" />

                </Storyboard>
            </BeginStoryboard>
        </Trigger.EnterActions>
        <Trigger.ExitActions>
            <RemoveStoryboard BeginStoryboardName="AnimateLoadingCanvas" />
            <BeginStoryboard Name="EndAnimateLoadingCanvas">
                <Storyboard FillBehavior="Stop">
                    <DoubleAnimation BeginTime="00:00:00"
                                     Duration="00:00:00.5"
                                     Storyboard.TargetName="MyViewBoxje"
                                     Storyboard.TargetProperty="Opacity"
                                     To="0" />
                    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00.5"
                                                   Storyboard.TargetName="MyViewBoxje"
                                                   Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
                    </ObjectAnimationUsingKeyFrames>

                </Storyboard>
            </BeginStoryboard>
        </Trigger.ExitActions>
    </Trigger>
</ControlTemplate.Triggers>

Странно то, чтокогда я использую этот элемент управления в тестовом окне и повторно нажимаю флажок «Загрузка» (и до завершения анимации), анимация постепенного исчезновения / исчезновения работает так, как я ожидаю.

Можеткто-нибудь поможет?Спасибо заранее!

Ответы [ 2 ]

3 голосов
/ 31 мая 2011

Трудно точно понять, в чем проблема, не видя остальной части кода, но я предполагаю, что это связано с начальными значениями анимированных свойств.

Я реализовал пользовательский элемент управления в WPFс прямоугольником внутри окна просмотра и использовали триггеры + раскадровки из вопроса, чтобы увидеть эффект.Действительно, моя первая попытка не исчезла и не исчезла.

Что я сделал, чтобы решить ее, так это указав From значения в анимации, чтобы они работали независимо от того, каково было первоначальное значение DP:

<DoubleAnimation BeginTime="00:00:00"
      Duration="00:00:00.5"
      Storyboard.TargetName="MyViewBoxje"
      Storyboard.TargetProperty="Opacity"
      From="0"
      To="1" />

Обратите внимание From="0" на вышеприведенную анимацию.Конечная раскадровка была изменена таким же образом, чтобы перейти от 1 к 0.

Для полноты я установил непрозрачность на 0 и для определения элемента viewbox внутри ControlTemplate.


Вот полный исходный код для соответствующих частей.Элемент управления является стандартным пользовательским элементом управления WPF, унаследованным от Control .У него есть одно свойство зависимости, называемое IsLoading (bool), которое по умолчанию равно false:

public bool IsLoading
{
    get { return (bool)GetValue(IsLoadingProperty); }
    set { SetValue(IsLoadingProperty, value); }
}

// Using a DependencyProperty as the backing store for IsLoading.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsLoadingProperty =
        DependencyProperty.Register("IsLoading", typeof(bool), typeof(LoadingControl), new UIPropertyMetadata(false));

ControlTemplate - определено в generic.xaml в стиле для {x:Type local:LoadingControl}

<ControlTemplate TargetType="{x:Type local:LoadingControl}">
    <ControlTemplate.Triggers>
        <Trigger Property="IsLoading" Value="True">
            <Trigger.EnterActions>
                <RemoveStoryboard BeginStoryboardName="EndAnimateLoadingCanvas" />
                <BeginStoryboard Name="AnimateLoadingCanvas">
                    <Storyboard FillBehavior="Stop">
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
                                   Storyboard.TargetName="MyViewBoxje"
                                   Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>

                        <DoubleAnimation BeginTime="00:00:00"
                                     Duration="00:00:00.5"
                                     Storyboard.TargetName="MyViewBoxje"
                                     Storyboard.TargetProperty="Opacity"
                                     From="0"
                                     To="1" />

                        <DoubleAnimation BeginTime="00:00:00"
                                         Duration="00:00:02"
                                         Storyboard.TargetName="AnimatedRotateTransform"
                                         Storyboard.TargetProperty="Angle"
                                         From="360"
                                         To="0"
                                         RepeatBehavior="Forever" />

                    </Storyboard>
                </BeginStoryboard>
            </Trigger.EnterActions>
            <Trigger.ExitActions>
                <RemoveStoryboard BeginStoryboardName="AnimateLoadingCanvas" />
                <BeginStoryboard Name="EndAnimateLoadingCanvas">
                    <Storyboard FillBehavior="Stop">
                        <DoubleAnimation BeginTime="00:00:00"
                                         Duration="00:00:00.5"
                                         Storyboard.TargetName="MyViewBoxje"
                                         Storyboard.TargetProperty="Opacity"
                                         From="1"
                                        To="0" />
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00.5"
                                   Storyboard.TargetName="MyViewBoxje"
                                   Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>

                    </Storyboard>
                </BeginStoryboard>
            </Trigger.ExitActions>
        </Trigger>
    </ControlTemplate.Triggers>

    <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}">
        <Viewbox x:Name="MyViewBoxje" Opacity="0">
            <!-- BG with 0x50 alpha so that it's translucent event at 100% visibility -->
            <Grid Width="100" Height="100" Background="#50000000">
                <Rectangle Width="70" Height="20" Fill="Green" Stroke="Black" StrokeThickness="2" RenderTransformOrigin="0.5,0.5">
                    <Rectangle.RenderTransform>
                        <RotateTransform Angle="360" x:Name="AnimatedRotateTransform" />
                    </Rectangle.RenderTransform>
                </Rectangle>
            </Grid>
        </Viewbox>
    </Border>
</ControlTemplate>

Я использовал в своем главном окне примерно так:

<Grid x:Name="LayoutRoot">
    <!-- All other stuff here ... -->

    <my:LoadingControl IsLoading="{Binding IsLoading}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>

И чтобы проверить это, у меня была ViewModel со свойством IsLoading, которое установлено как DataContext для основногоокно.И в конструкторе ViewModel я устанавливаю IsLoading в true и затем запускаю таймер, который переключает значение свойства каждые 5 секунд:

public MainWindowViewModel()
{
    IsLoading = true;
    DispatcherTimer t = new DispatcherTimer();
    t.Interval = TimeSpan.FromSeconds(5);
    t.Tick += (s, e) => IsLoading = !IsLoading;
    t.Start();
}
0 голосов
/ 01 июня 2011

Я наконец понял это после прочтения ответа Исака.Сожалею, что его ответ не помог в моем случае, но он заставил меня двигаться в правильном направлении.

Причина, по которой первое постепенное появление, похоже, не сработало, заключалась в том, что в моем содержащем окне просмотра была установлена ​​видимостьчтобы рухнуть все время была выполнена анимация появления.Это было вызвано ObjectAnimationUsingKeyFrames:

    DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>

Не указана длительность, и указанный ключевой кадр был анимирован слишком поздно.

Добавление

Duration="00:00:00"

решило моюпроблема.

Спасибо вам всем за помощь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...