Нужно сделать компонет вроде 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 выполняется в совершенно произвольные моменты, часто вызывая зависание. Подскажите, пожалуйста, как отследить тот момент, когда первая анимация реально завершилась.
Здравствуйте, 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();
}
}
}));
Здравствуйте, 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 при некоторых запусках анимации вообще не срабатывает, срабатывает только со второго запуска. И ещё одна проблема обнаружилась — я не нашёл ни одного свойства, которое б точно подсказало б, запущена ли анимация в настоящий момент. Вот вопрос, как это преодолеть.
Здравствуйте, Ilya81, Вы писали:
Здесь почитайте
Если вам нужно выполнить одну анимацию за другой, то это то, что надо.
Здравствуйте, Codechanger, Вы писали:
C>Здравствуйте, Ilya81, Вы писали:
C>Здесь почитайте
C>Если вам нужно выполнить одну анимацию за другой, то это то, что надо.
В общем разобрался, т. с. на случай, если у кого будет такая ж проблема: оказалось, надо всего лишь подписываться на событие до запуска анимации.