Как анимировать ContentControl в ItemsControl
Мне нравится использовать ItemsControl для размещения ContentsControls. Каждый новый ContentsControl анимирует свое содержимое при добавлении элемента и каждого ContentControl и перекрывает предыдущий. ItemsControl и ContentControl Content связаны с Caliburn Micro с использованием соглашений об именах.
<ItemsControl x:Name="OverlayStackedItems" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Transparent">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid x:Name="ItemsHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<cc:DummyContentControl cal:View.Model="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
ContentControl определяется следующим образом:
[ContentProperty("Content")]
public partial class DummyContentControl :ContentControl
{
public DummyContentControl()
{
}
static DummyContentControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DummyContentControl), new FrameworkPropertyMetadata(typeof(ContentControl)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
protected override void OnContentChanged(object oldContent, object newContent)
{
LayoutUpdated += (sender, e) =>
{
};
UpdateLayout();
base.OnContentChanged(oldContent, newContent);
}
void DummyContentControl_LayoutUpdated(object sender, EventArgs e)
{
throw new NotImplementedException();
}
protected override Size MeasureOverride(Size constraint)
{
return base.MeasureOverride(constraint);
}
}
Итак, наконец, мой вопрос. В реальном ContentControl мне нравится анимировать Content, но ContentControl имеет размер 0, когда OnContentChange вызывается там, где создается моя анимация. Порядок вызовов при размещении ContentControl в ItemsControl:
- OnContentChanged (Ошибка анимации)
- OnApplyTemplate
- MeasureOverride
Когда ContentControl запускается сам по себе, порядок:
- OnApplyTemplate
- MeasureOverride
- OnContentChanged (Анимация работает)
Проблема здесь в том, что полное визуальное поддерево нового Item в ItemsControl равно 0 (DesiredSize,ActualSize = 0), поэтому мой код анимации завершается ошибкой. Я надеюсь, что это имеет смысл для кого-то, Любая помощь будет отличной, Thx, J
------------------------------ Редакция -------------------
Хорошо, я добавил обработчик событий OnLoaded в ctor DummyControl. Порядок вызовов: 1. OnContentChanged (все размеры равны 0) 2. OnApplyTemplate (все размеры равны 0) 3. MeasureOverride (вызывается несколько раз, вероятно, для всех дочерних элементов управления, размещенных ContentControl) 4. Загруженное событие (требуемый размер устанавливается всеми другие размеры еще 0)
Может кто-нибудь объяснить, что такое рекомендуемая практика, как анимировать хостет ContentControl с помощью ItemsControl?
1 ответ
Просто сделайте все в XAML, и пусть анимация сделает свое дело, не вызывая MeasureOverride() и остальные хуки.
<ItemsControl>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border>
<TextBlock Text="Whatever your template should look like"/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleX)" Duration="0:0:0.5" From="0" To="1" />
<DoubleAnimation Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.ScaleY)" Duration="0:0:0.5" From="0" To="1" />
<DoubleAnimation Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.CenterX)" Duration="0:0:0.5" To="25" />
<DoubleAnimation Storyboard.TargetProperty="(Border.RenderTransform).(ScaleTransform.CenterY)" Duration="0:0:0.5" To="25" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>