Страницы

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

среда, 10 июля 2019 г.

Как анимировать динамически создаваемые контролы XAML

У меня есть список, с привязкой к данным. В этом списке есть элемент, который требуется анимировать. Допустим гиппотечиская страничка может выглядеть так:




В данном примере по Тапу на элементе списка должен появляться скрытый черный квадратик. Однако на практике приложение падает с ошибкой
System.Exception: No installed components were detected. Cannot resolve TargetName Control. at Windows.UI.Xaml.Media.Animation.Storyboard.Begin() at Microsoft.Xaml.Interactions.Media.ControlStoryboardAction.Execute(Object sender, Object parameter) at Microsoft.Xaml.Interactivity.Interaction.ExecuteActions(Object sender, ActionCollection actions, Object parameter) at Microsoft.Xaml.Interactions.Core.EventTriggerBehavior.OnEvent(Object sender, Object eventArgs)
Может можно как-то по-другому сделать?


Ответ

У меня сработало так (пробовал только на UWP под Windows 10):


Проблема в том, что имя Control, на которое ссылается ваша анимация через Storyboard.TargetName, должно быть видимо на этапе компиляции. Когда анимация и DataTemplate описаны вместе, они видят друг друга.

Обновление: если вам нужно проигрывать разные анимации, можно использовать переключение в code-behind. Например, так:
False True False

и в code-behind:
void Grid_Tapped(object sender, TappedRoutedEventArgs e) { var grid = (Grid)sender; grid.Tag = !(bool)grid.Tag; }

Ну и если вам не нужна реальная анимация, а только включить/выключить видимость элемента, можно ещё проще:

и в code-behind
void Grid_Tapped(object sender, TappedRoutedEventArgs e) { var grid = (Grid)sender; var control = (StackPanel)grid.FindName("Control"); control.Visibility = control.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed; }

Ну и ещё один вариант, без code-behind, но с одним конвертером. Идея в том, что мы по событию tapped меняем значение Tag между true и false, а к этому значению через DataTrigger прикрепляем анимацию.
False True False

Вам понадобится всего лишь простой конвертер:
class BooleanNegatingConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string lang) { return !(bool)value; }
public object ConvertBack(object value, Type targetType, object parameter, string lang) { return !(bool)value; } }

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

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