代码隐藏中的WPF UserControl动画不使用ContentPresenter

时间:2013-10-12 15:40:48

标签: c# wpf xaml animation

当代码如下所示时,动画正常工作

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代码中使用ContentPresenter时,动画根本不起作用

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

当我尝试使用网格包装ContentPresenter时,动画仍然不起作用

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

这是问题所在。 如何让动画与ContentPresenter一起使用?

更新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;
        }

1 个答案:

答案 0 :(得分:1)

所以问题在于你如何使用你的用户控件 - 你只需在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);
        }
    }