[WPF]Анимация не выдаёт событие Completed
От: Ilya81  
Дата: 11.08.11 14:50
Оценка:
Нужно сделать компонет вроде NumericUpDown в WPF, но где б ещё при изменении цифр они б не просто менялись, а первая цифра б поднималась за пределы компонента, а нижняя — поднималась снизу. С анимацией раньше дело не имел, но написал такое

<Storyboard x:Key="BeforeChangeStoryboard" Duration="0:0:0.3">
                <DoubleAnimationUsingKeyFrames BeginTime="0:0:0" Duration="0:0:0.3" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="grid1">
                    <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="-20"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>
            <Storyboard x:Key="AfterChangeStoryboard" Duration="0:0:0.3">
                <DoubleAnimationUsingKeyFrames BeginTime="0:0:0" Duration="0:0:0.3" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="grid1">
                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="20"/>
                    <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
                </DoubleAnimationUsingKeyFrames>
            </Storyboard>


Первая часть вызывается из свойства

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown), new UIPropertyMetadata(0m, (_d, _e) =>
            {
                if ((decimal)_e.NewValue != (decimal)_e.OldValue)
                {
                    decimal newValue = (decimal)_e.NewValue;
                    NumericUpDown thisControl = _d as NumericUpDown;
                    if (newValue >= thisControl.MinValue && newValue <= thisControl.MaxValue)
                    {
                        Storyboard animation = thisControl.Resources["BeforeChangeStoryboard"] as Storyboard;
                        animation.Begin(thisControl.Template.FindName("grid1", thisControl) as Grid);
                        animation.Completed += (_s, _e2) => thisControl.Text = newValue.ToString();
                    }
                }
            }));


А вторая происходит по триггеру

<EventTrigger RoutedEvent="TextBox.TextChanged">
                    <BeginStoryboard Storyboard="{StaticResource AfterChangeStoryboard}"/>
                </EventTrigger>


Реально событие animation.Completed выполняется в совершенно произвольные моменты, часто вызывая зависание. Подскажите, пожалуйста, как отследить тот момент, когда первая анимация реально завершилась.
Re: [WPF]Анимация не выдаёт событие Completed
От: MxMsk Португалия  
Дата: 12.08.11 06:38
Оценка:
Здравствуйте, Ilya81, Вы писали:

I>Нужно сделать компонет вроде NumericUpDown в WPF, но где б ещё при изменении цифр они б не просто менялись, а первая цифра б поднималась за пределы компонента, а нижняя — поднималась снизу. С анимацией раньше дело не имел, но написал такое

Выложи какой-нибудь примерчик для воспроизведения.

I>Первая часть вызывается из свойства

А тут я бы хотел сделать несколько комментариев:
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown), new UIPropertyMetadata(0m, (_d, _e) =>
            {
                if ((decimal)_e.NewValue != (decimal)_e.OldValue)
                {
                    // Не зачем делать анбоксинг два раза. У тебя выходит один анбоксинг в условии и повторный здесь.
                    // Вынес бы данную строчку в начало метода и использовал newValue в проверке.
                    decimal newValue = (decimal)_e.NewValue;

                    // Далее везде корректнее использовать прямое приведение, вместо as.
                    // as уместно использовать в случае, когда учитывается null.
                    // Иначе можно неожиданно схлопотать NullReferenceException вместо InvalidCastException в месте приведения.
                    NumericUpDown thisControl = _d as NumericUpDown;
                    if (newValue >= thisControl.MinValue && newValue <= thisControl.MaxValue)
                    {
                        Storyboard animation = thisControl.Resources["BeforeChangeStoryboard"] as Storyboard;
                        animation.Begin(thisControl.Template.FindName("grid1", thisControl) as Grid);
                        animation.Completed += (_s, _e2) => thisControl.Text = newValue.ToString();
                    }
                }
            }));
Re[2]: [WPF]Анимация не выдаёт событие Completed
От: Ilya81  
Дата: 12.08.11 10:35
Оценка:
Здравствуйте, MxMsk, Вы писали:

MM>Здравствуйте, Ilya81, Вы писали:


I>>Нужно сделать компонет вроде NumericUpDown в WPF, но где б ещё при изменении цифр они б не просто менялись, а первая цифра б поднималась за пределы компонента, а нижняя — поднималась снизу. С анимацией раньше дело не имел, но написал такое

MM>Выложи какой-нибудь примерчик для воспроизведения.

I>>Первая часть вызывается из свойства

MM>А тут я бы хотел сделать несколько комментариев:
MM>
MM>        public static readonly DependencyProperty ValueProperty =
MM>            DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown), new UIPropertyMetadata(0m, (_d, _e) =>
MM>            {
MM>                if ((decimal)_e.NewValue != (decimal)_e.OldValue)
MM>                {
MM>                    // Не зачем делать анбоксинг два раза. У тебя выходит один анбоксинг в условии и повторный здесь.
MM>                    // Вынес бы данную строчку в начало метода и использовал newValue в проверке.
MM>                    decimal newValue = (decimal)_e.NewValue;

MM>                    // Далее везде корректнее использовать прямое приведение, вместо as.
MM>                    // as уместно использовать в случае, когда учитывается null.
MM>                    // Иначе можно неожиданно схлопотать NullReferenceException вместо InvalidCastException в месте приведения.
MM>                    NumericUpDown thisControl = _d as NumericUpDown;
MM>                    if (newValue >= thisControl.MinValue && newValue <= thisControl.MaxValue)
MM>                    {
MM>                        Storyboard animation = thisControl.Resources["BeforeChangeStoryboard"] as Storyboard;
MM>                        animation.Begin(thisControl.Template.FindName("grid1", thisControl) as Grid);
MM>                        animation.Completed += (_s, _e2) => thisControl.Text = newValue.ToString();
MM>                    }
MM>                }
MM>            }));
MM>


Примеров нет, примеры только в мыслях. Подправить на тему ненужных повторов я успею, сейчас главное, чтоб сработало, а потом можно оптимизировать. Вот событие Completed при некоторых запусках анимации вообще не срабатывает, срабатывает только со второго запуска. И ещё одна проблема обнаружилась — я не нашёл ни одного свойства, которое б точно подсказало б, запущена ли анимация в настоящий момент. Вот вопрос, как это преодолеть.
Re: [WPF]Анимация не выдаёт событие Completed
От: Codechanger Россия  
Дата: 12.08.11 17:54
Оценка:
Здравствуйте, Ilya81, Вы писали:

Здесь почитайте

Если вам нужно выполнить одну анимацию за другой, то это то, что надо.
Re[2]: [WPF]Анимация не выдаёт событие Completed
От: Ilya81  
Дата: 16.08.11 05:25
Оценка:
Здравствуйте, Codechanger, Вы писали:

C>Здравствуйте, Ilya81, Вы писали:


C>Здесь почитайте


C>Если вам нужно выполнить одну анимацию за другой, то это то, что надо.


В общем разобрался, т. с. на случай, если у кого будет такая ж проблема: оказалось, надо всего лишь подписываться на событие до запуска анимации.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.