I'm trying to fire an animation when a content control such as Button or ContentControl changes its content. My initial thoughts were to do this:
<ContentControl x:Name="ContentElement">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<ContentPresenter x:Name="Content">
<ContentPresenter.Triggers>
<EventTrigger RoutedEvent="WHATGOESHERE">
<BeginStoryboard Storyboard="{StaticResource MyAnimation}" Storyboard.TargetName="Content"/>
</EventTrigger>
</ContentPresenter.Triggers>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ContentControl.Style>
<Button Content="Hello"/>
</ContentControl>
But I don't know which event fires when the ContentPresenter is changed/updated. Any ideas?
You can just write an attached property:
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
static class ContentControlExtensions
{
public static readonly DependencyProperty ContentChangedAnimationProperty = DependencyProperty.RegisterAttached(
"ContentChangedAnimation", typeof(Storyboard), typeof(ContentControlExtensions), new PropertyMetadata(default(Storyboard), ContentChangedAnimationPropertyChangedCallback));
public static void SetContentChangedAnimation(DependencyObject element, Storyboard value)
{
element.SetValue(ContentChangedAnimationProperty, value);
}
public static Storyboard GetContentChangedAnimation(DependencyObject element)
{
return (Storyboard)element.GetValue(ContentChangedAnimationProperty);
}
private static void ContentChangedAnimationPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var contentControl = dependencyObject as ContentControl;
if (contentControl == null)
throw new Exception("Can only be applied to a ContentControl");
var propertyDescriptor = DependencyPropertyDescriptor.FromProperty(ContentControl.ContentProperty,
typeof (ContentControl));
propertyDescriptor.RemoveValueChanged(contentControl, ContentChangedHandler);
propertyDescriptor.AddValueChanged(contentControl, ContentChangedHandler);
}
private static void ContentChangedHandler(object sender, EventArgs eventArgs)
{
var animateObject = (FrameworkElement) sender;
var storyboard = GetContentChangedAnimation(animateObject);
storyboard.Begin(animateObject);
}
}
and then in XAML:
<ContentControl Content="{Binding SelectedViewItem}">
<extensions:ContentControlExtensions.ContentChangedAnimation>
<Storyboard>
<ThicknessAnimation To="0" From="30,0,-30,0" Duration="0:0:0.3" Storyboard.TargetProperty="Margin"/>
</Storyboard>
</extensions:ContentControlExtensions.ContentChangedAnimation>
</ContentControl>
It's much easier and shorter than a new control.
There is no CLR-event for ContentChanged (much less a RoutedEvent required for EventTriggers) unfortunately. However, given that you're dealing with a custom control, you can override the metadata for the Content property and provide your own callback within the control.
This may be about what you're looking for here
Obviously he's created a CLR-event to propagate content changes externally; you could also do the same just using a RoutedEvent instead.
Additional reading on OverrideMetadata here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With