0

Подскажите, пожалуйста, как решить проблему. Я делаю анимацию смены UserControl, решение нашел сдесь: Как анимировать смену одного контрола на другой?

Анимация работает, но когда меняется предыдущий UserControl при выборе нового, то он не анимируется, а просто исчезает и начинает работать анимация выбранного UserControl.

  [TemplatePart(Name = "PART_Animation", Type = typeof(Storyboard))]
public class AnimatableContentPresenter : Control
{
    static AnimatableContentPresenter()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(AnimatableContentPresenter),
            new FrameworkPropertyMetadata(typeof(AnimatableContentPresenter)));
    }

    Storyboard animation; // текущая анимация
    bool isAnimationRunning = false;

    #region dp object Content, on change OnContentChanged
    public object Content
    {
        get { return (object)GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }

    public static readonly DependencyProperty ContentProperty =
        DependencyProperty.Register(
            "Content", typeof(object), typeof(AnimatableContentPresenter),
            new PropertyMetadata(OnContentChangedStatic));

    static void OnContentChangedStatic(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var self = (AnimatableContentPresenter)d;
        self.OnContentChanged(e.OldValue, e.NewValue);
    }
    #endregion

    #region dp object PreviousContent
    public object PreviousContent
    {
        get { return (object)GetValue(PreviousContentProperty); }
        set { SetValue(PreviousContentProperty, value); }
    }

    public static readonly DependencyProperty PreviousContentProperty =
        DependencyProperty.Register(
            "PreviousContent", typeof(object), typeof(AnimatableContentPresenter));
    #endregion

    // когда Content поменяется...
    void OnContentChanged(object oldContent, object newContent)
    {
        if (isAnimationRunning)
            animation?.Stop();

        // ... запомним старый Content в PreviousContent
        PreviousContent = oldContent;

        // и перезапустим анимацию
        if (animation != null)
        {
            animation.Begin();
            isAnimationRunning = true;
        }
    }

    // при появлении шаблона, вычитаем из него анимацию
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        if (animation != null)
            animation.Completed -= OnAnimationCompleted;

        if (isAnimationRunning)
        {
            // TODO: начать новую анимацию там, где предыдущая завершилась?
            animation?.Stop();
        }

        animation = (Storyboard)Template.FindName("PART_Animation", this);

        if (animation != null) // подпишемся на завершение анимации
            animation.Completed += OnAnimationCompleted;
    }

    // по окончанию анимации...
    private void OnAnimationCompleted(object sender, EventArgs e)
    {
        // выбросим старый контент
        PreviousContent = null;
        // сбросим эффект анимации
        animation.Remove();
        isAnimationRunning = false;
    }
}

Стиль:

   <Style TargetType="{x:Type local:AnimatableContentPresenter}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:AnimatableContentPresenter}">
                <!-- несколько трюков с layout manager'ом, чтобы
                 избежать умножения через конвертер -->
                <Grid Name="Root" ClipToBounds="True">
                    <Grid HorizontalAlignment="Left">
                        <!-- ширина вдвое больше Root -->
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition
                            Width="{Binding ActualWidth, ElementName=Root}"/>
                            <ColumnDefinition
                            Width="{Binding ActualWidth, ElementName=Root}"/>
                        </Grid.ColumnDefinitions>
                        <!-- растянем на всю ширину -->
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"
                                Grid.ColumnSpan="2">
                            <!-- старый контент -->
                            <ContentPresenter
                            Content="{TemplateBinding PreviousContent}"
                            Style="{x:Null}"
                            Width="{Binding ActualWidth, ElementName=Root}"/>
                            <!-- текущий контент -->
                            <ContentPresenter
                            Content="{TemplateBinding Content}"
                            Style="{x:Null}"
                            Width="{Binding ActualWidth, ElementName=Root}"/>
                            <!-- анимируемая распорка -->
                            <Grid Width="{Binding ActualWidth, ElementName=Root}"
                              Name="Strut">
                                <Grid.Resources>
                                    <Storyboard x:Key="Animation" x:Name="PART_Animation">
                                        <DoubleAnimation
                                        Storyboard.TargetName="Strut"
                                        Storyboard.TargetProperty="Width"
                                        From="0"
                                        Duration="0:0:0.4">
                                            <DoubleAnimation.EasingFunction>
                                                <ExponentialEase EasingMode="EaseInOut"
                                                             Exponent="1.2"/>
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                    </Storyboard>
                                </Grid.Resources>
                            </Grid>
                        </StackPanel>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ListBox:

       <ListBox ItemsSource="{Binding ElementName=Control, Path=ItemsSource}"
             SelectedItem="{Binding ElementName=Control,Path=SelectedItem}"
             BorderThickness="0" Background="Transparent"
             ItemContainerStyle="{StaticResource CustomListBoxItem}" Width="50"
             ScrollViewer.VerticalScrollBarVisibility="Disabled"/>


 <local:NavigationMenu ItemsSource="{Binding MenuItem, Mode=TwoWay}"
                          SelectedItem="{Binding SelectedMenu, Mode=TwoWay}"/>

ContentControl:

           <ContentControl Content="{Binding CurrentContent, Mode=TwoWay, IsAsync=True}"
                        Style="{StaticResource LeftToRightAnimatedContentControl}"/>

Стиль ContentControl:

    <Style TargetType="{x:Type ContentControl}" x:Key="LeftToRightAnimatedContentControl">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Grid>
                    <local:AnimatableContentPresenter Content="{Binding}"/>
                </Grid>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

0 Answers0