代码隐藏中的 WPF 用户控件动画不使用内容演示器

本文关键字:动画 隐藏 WPF 控件 用户 代码 | 更新日期: 2023-09-27 18:35:09

当代码像这样时,动画会按预期工作

AnimatedUserControl2.xaml

<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
    <Grid Background="Coral">
        <Canvas>
            <TextBlock x:Name="MNB" Text="ABCD"/>
        </Canvas>
    </Grid>
</UserControl>

AnimatedUserControl2.xaml.cs(仅限部分代码)

        private void AnimatedUserControl2_OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (Visibility == Visibility.Visible)
            {
                var storyboard = new Storyboard();
                var visibilityAnimation = new ObjectAnimationUsingKeyFrames();
                visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame(Visibility.Visible,
                                                                             KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
                Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath(VisibilityProperty));
                storyboard.Children.Add(visibilityAnimation);
                var opacityAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(1)));
                Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(OpacityProperty));
                storyboard.Children.Add(opacityAnimation);
                var canvasLeftAnimation = new DoubleAnimationUsingKeyFrames();
                canvasLeftAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(200,
                                                                           KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
                canvasLeftAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)),
                                                                           new KeySpline(new Point(0.25, 0.1),
                                                                                         new Point(0.25, 1))));
                Storyboard.SetTargetProperty(canvasLeftAnimation, new PropertyPath(Canvas.LeftProperty));
                storyboard.Children.Add(canvasLeftAnimation);
                MNB.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, false);
            }
        }

但是,当我在 XAML 代码中使用内容演示器时,动画根本不起作用

动画用户控件2.xaml(第 1 版)

<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
    <Grid Background="Coral">
        <Canvas>
            <ContentPresenter x:Name="MNB"/>
        </Canvas>
    </Grid>
</UserControl>

当我尝试用网格包装内容演示器时,动画仍然不起作用

动画用户控件2.xaml(第2版)

<UserControl x:Class="WpfPoc20120908.AnimatedUserControl2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" IsVisibleChanged="AnimatedUserControl2_OnIsVisibleChanged">
    <Grid Background="Coral">
        <Canvas>
            <Grid x:Name="MNB">
                <ContentPresenter/>
            </Grid>
        </Canvas>
    </Grid>
</UserControl>

问题来了。如何让动画与内容演示器配合使用?

更新 01

以下是 AnimatedUserControl2 的使用方式。

MainWindow.xaml(仅限部分代码)

        <StackPanel Grid.Row="0" Orientation="Vertical">
            <usercontrols:AnimatedUserControl2 x:Name="ABCD" Visibility="Hidden">
                <TextBlock Text="ABC"/>
            </usercontrols:AnimatedUserControl2>
            <usercontrols:AnimatedUserControl2 x:Name="EFGH" Visibility="Hidden" Margin="10">
                <TextBlock Text="ABC"/>
            </usercontrols:AnimatedUserControl2>
        </StackPanel>
        <Button x:Name="ButtonBeginAnimation" Click="ButtonBeginAnimation_OnClick" Content="Begin Animation" Grid.Row="1"/>

MainWindow.xaml.cs(仅限部分代码)

        private void ButtonBeginAnimation_OnClick(object sender, RoutedEventArgs e)
        {
            ABCD.Visibility = (ABCD.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;
            EFGH.Visibility = (EFGH.Visibility == Visibility.Visible) ? Visibility.Collapsed : Visibility.Visible;
        }

代码隐藏中的 WPF 用户控件动画不使用内容演示器

因此,问题在于您如何使用用户控件 - 您只需在 UserControl xaml 定义中指定后重写内容...无论如何。。尝试这种方法(动画在我的机器上工作,所以假设也可以在你的机器上工作;))

<UserControl x:Class="WpfApplication11.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
<UserControl.Template>
    <ControlTemplate TargetType="UserControl">
        <Grid Background="Coral">
            <Canvas>
                <ContentPresenter x:Name="MNB" Content="{TemplateBinding Content}"/>
            </Canvas>
        </Grid>
    </ControlTemplate>
</UserControl.Template>

而在动画本身中:

  private void AnimatedUserControl2_OnIsVisibleChanged(object sender, EventArgs e)
    {
        var mnb = Template.FindName("MNB", this) as FrameworkElement;
        if (mnb == null)
        {
            return;
        }
        if (Visibility == Visibility.Visible)
        {
            var storyboard = new Storyboard();
            var visibilityAnimation = new ObjectAnimationUsingKeyFrames();
            visibilityAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame(Visibility.Visible,
                                                                         KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            Storyboard.SetTargetProperty(visibilityAnimation, new PropertyPath(VisibilityProperty));
            storyboard.Children.Add(visibilityAnimation);
            var opacityAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(1)));
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(OpacityProperty));
            storyboard.Children.Add(opacityAnimation);
            var canvasLeftAnimation = new DoubleAnimationUsingKeyFrames();
            canvasLeftAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(200,
                                                                       KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0))));
            canvasLeftAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1)),
                                                                       new KeySpline(new Point(0.25, 0.1),
                                                                                     new Point(0.25, 1))));
            Storyboard.SetTargetProperty(canvasLeftAnimation, new PropertyPath(Canvas.LeftProperty));
            storyboard.Children.Add(canvasLeftAnimation);
            mnb.BeginStoryboard(storyboard, HandoffBehavior.SnapshotAndReplace, false);
        }
    }