Вопрос по wpf, c#, xaml – Начать анимацию, когда ContentControl.Content изменяется

4

Я пытаюсь запустить анимацию, когда такой элемент управления содержимым, как Button или ContentControl, меняет свое содержимое. Мои первые мысли были сделать это:

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

Но я не знаю, какое событие возникает, когда ContentPresenter изменяется / обновляется. Есть идеи?

Ваш Ответ

2   ответа
1

К сожалению, для ContentChanged нет CLR-события (тем более, что для EventTriggers требуется RoutedEvent). Однако, учитывая, что вы имеете дело с пользовательским элементом управления, вы можете переопределить метаданные для свойства Content и предоставить свой собственный обратный вызов внутри элемента управления.

Это может быть то, что вы ищетеВот

Очевидно, он создал CLR-событие для внешнего распространения изменений контента; вы также можете сделать то же самое, просто используя RoutedEvent.

Дополнительное чтение по OverrideMetadataВот

10

Вы можете просто написать прикрепленное свойство:

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>

Это намного проще и короче, чем новый элемент управления.

Это не поведение, это присоединенное свойство.
Если вы изменитеDependencyObject выноски вGet.. а такжеSet... методы дляContentControlВам не нужно выполнять проверку типа в методе обратного вызова.
@EmperorAiman вы правы, я изменил это, спасибо :)
Отличный пример, красивый и простой .... для новых разработчиков WPF может быть просто стоит добавить xmlns: поведение = & quot; clr-namespace: & lt; ваше пространство имен приложения & gt; & quot; на вершину XAML .....

Похожие вопросы