Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Как анимировать смену одного контрола на другой?

#c_sharp #net #wpf #mvvm


В зависимости от привязанной к ContentPresenter Vm-ки, на экране отображаются разные
UserControl. Можно ли как-то отловить момент смены одного контрола на другой, чтобы
санимировать этот переход?


        
            
                
            
            
                
            
        


    


Ответы

Ответ 1



Окей, комментарий @Squidward @Athari на самом деле правильный: в Mahapps.Metro есть нужный контрол с несколькими предопределёнными анимациями. Но давайте напишем такой контрол самостоятельно. Перед нами стоят две проблемы. Во-первых, мы должны запомнить старый контент перед тем, как он исчезнет, чтобы правильно показать его на время анимации. Во-вторых, для показа одновременно и старого, и нового контента нам нужны два ContentPresenter'а. Для этого воспользуемся промежуточным контролом, который будет содержать эти самые два ContentPresenter'а. Итак, создаём новый контрол, назовём его AnimatableContentPresenter. Мы создаёт custom control, а не UserControl. (Это делается через Проект → Add → New Item... → WPF → Custom Control (WPF) в Visual Studio.) Для начала, код с комментариями. // объявляем, что в шаблоне должна быть предоставлена анимация, которую мы запустим [TemplatePart(Name = "PART_Animation", Type = typeof(Storyboard))] public class AnimatableContentPresenter : Control { static AnimatableContentPresenter() { DefaultStyleKeyProperty.OverrideMetadata( typeof(AnimatableContentPresenter), new FrameworkPropertyMetadata(typeof(AnimatableContentPresenter))); } Storyboard animation; // текущая анимация bool isAnimationRunning = false; #region dp object Content, on change OnContentChanged public object Content { get { return (object)GetValue(ContentProperty); } set { SetValue(ContentProperty, value); } } public static readonly DependencyProperty ContentProperty = DependencyProperty.Register( "Content", typeof(object), typeof(AnimatableContentPresenter), new PropertyMetadata(OnContentChangedStatic)); static void OnContentChangedStatic( DependencyObject d, DependencyPropertyChangedEventArgs e) { var self = (AnimatableContentPresenter)d; self.OnContentChanged(e.OldValue, e.NewValue); } #endregion #region dp object PreviousContent public object PreviousContent { get { return (object)GetValue(PreviousContentProperty); } set { SetValue(PreviousContentProperty, value); } } public static readonly DependencyProperty PreviousContentProperty = DependencyProperty.Register( "PreviousContent", typeof(object), typeof(AnimatableContentPresenter)); #endregion // когда Content поменяется... void OnContentChanged(object oldContent, object newContent) { if (isAnimationRunning) animation?.Stop(); // ... запомним старый Content в PreviousContent PreviousContent = oldContent; // и перезапустим анимацию if (animation != null) { animation.Begin(); isAnimationRunning = true; } } // при появлении шаблона, вычитаем из него анимацию public override void OnApplyTemplate() { base.OnApplyTemplate(); if (animation != null) animation.Completed -= OnAnimationCompleted; if (isAnimationRunning) { // TODO: начать новую анимацию там, где предыдущая завершилась? animation?.Stop(); } animation = (Storyboard)Template.FindName("PART_Animation", this); if (animation != null) // подпишемся на завершение анимации animation.Completed += OnAnimationCompleted; } // по окончанию анимации... private void OnAnimationCompleted(object sender, EventArgs e) { // выбросим старый контент PreviousContent = null; // сбросим эффект анимации animation.Remove(); isAnimationRunning = false; } } Теперь нам нужен шаблон в Themes\Generic.xaml (его вам уже, скорее всего, положил мастер создания нового контрола). Отлично, большая часть работы готова. Теперь нам нужно представить это как стиль для чего-нибудь — например, для ContentControl'а. (Это штука наподобие ContentPresenter'аб немного более высокоуровневая.) Кладём в нашем окне (или ресурсах приложения) стиль: Испытываем. Получаем вот такую анимацию:

Ответ 2



Это надо делать DataTrigger + StoryBoard (вот тут пример есть). Цепляешься в твоем случае к свойствам IsLoginFineshed (к примеру) и на него цепляешь анимацию.

Комментариев нет:

Отправить комментарий