更改 ContentControl.Content 时开始动画

本文关键字:开始 动画 Content ContentControl 更改 | 更新日期: 2023-09-27 18:36:04

我正在尝试在内容控件(如按钮或内容控件)更改其内容时触发动画。我最初的想法是这样做:

        <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>

但我不知道当内容演示器被更改/更新时,哪个事件会触发。有什么想法吗?

更改 ContentControl.Content 时开始动画

您可以只编写一个附加属性:

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);
    }
}

然后在 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>

它比新控件更容易、更短。

不幸的是,ContentChanged 没有 CLR 事件(更不用说 EventTrigger 所需的 RoutedEvent)。 但是,假设您正在处理自定义控件,则可以重写 Content 属性的元数据,并在控件中提供自己的回调。

这可能是你在这里寻找的内容

显然,他创建了一个 CLR 事件来向外部传播内容更改;您也可以使用 RoutedEvent 来执行相同的操作。

此处有关覆盖元数据的其他阅读材料