使用 VisualTreeHelper 的 DoubleAnimation 只工作一次

DoubleAnimation using VisualTreeHelper works only once

查看发生了什么的一些代码:

XAML 文件:

<!-- put this code into your page xaml code-->

<Page.Resources>
    <Style x:Name="opabuttonstyle" TargetType="Button">
        <Setter Property="Margin" Value="10" />
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
    </Style>
</Page.Resources>

<Grid Background="{StaticResource BackgroundGradient-Blue}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid Grid.Row="0" HorizontalAlignment="Center">
        <Button
            x:Name="testingIsTheFutureButton"
            Grid.Row="0"
            Grid.Column="0"
            Click="testingIsTheFutureButton_Click"
            Content="Opacity Animation"
            Style="{StaticResource opabuttonstyle}" />
    </Grid>
    <Grid Grid.Row="1">
        <StackPanel x:Name="stackingStackPanel" HorizontalAlignment="Center">
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
            <TextBlock Text="Element" />
        </StackPanel>
    </Grid>
</Grid>

Class 文件 SingleAnimations.cs:

// This function takes UIElement and DoubleAnimate it to fade in.
public static void SimpleElementFadeIn(object sender, int fadeTime, int delay)
{
        UIElement element = sender as UIElement;    //bierz element
        Storyboard storyboard = new Storyboard();
        DoubleAnimation doubleAnimation = new DoubleAnimation();
        doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, delay);
        doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, fadeTime));
        doubleAnimation.From = 0;
        doubleAnimation.To = 1;
        Storyboard.SetTarget(doubleAnimation, element);
        Storyboard.SetTargetProperty(doubleAnimation, "Opacity");
        storyboard.Children.Add(doubleAnimation);
        storyboard.Begin();
}

Class 文件 CollectionAnimations.cs:

// This function goes through every children element in UIElement (grid, 
//stackpanel or whatever we send there) and animates it using previous function
public static void OpacityWithChildren_Light(object sender, int delay)
{
    SetOpacityToZero_Deep(sender);  // set opacity to 0 to all elements before animation
    UIElement rootElement = sender as UIElement;   
    int childCount= VisualTreeHelper.GetChildrenCount(rootElement);
    if (childCount > 0)
    {
        for (int index = 0; index < childCount; index++)
        {
                UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index);
                SingleAnimations.SimpleElementFadeIn(element, 100, delay * index);
        }
    }
}

// This function goes through every children element like the funtion above
// and sets opacity of these elements to 0 (so every element is invisible before it's animated)
public static void SetOpacityToZero_Deep(object sender)
{
    UIElement rootElement = sender as UIElement;
    int childNumber = VisualTreeHelper.GetChildrenCount(rootElement);
    if (childNumber > 0)
    {
        for (int index = 0; index < childNumber; index++)
        {
            UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index);
                element.Opacity = 0;
        }
    }
}

启动动画我调用

CollectionAnimations.OpacityWithChildren_Light(stackingStackPanel, 50);

button_click 事件中。

我期望的是 StackPanel 中的所有 TextBlocks 都消失并且将一个接一个地淡入淡出。这种情况正在发生,但仅限于首次使用。如果我再次单击该按钮,那么所有这些都可见并且一个一个地动画化——这不是我想要发生的。如果我返回 MainPage 并再次进入该页面,它将像以前一样再次(一次)工作。

我也许应该清理一些现金。我没有在文档中遇到类似的东西,或者我只是错过了它。对于独立动画,没有提到过类似的东西。我弄乱了这段代码,尝试了不同的东西和方法,但没有成功。

我建议您应该能够使用两个 Storyboard 来做到这一点,一个将 Opacity 设置为 0,另一个根据需要播放 DoubleAnimation

所以我们不需要通过UIElement.OpacityOpacity设置为0。当 StoryboardOpacity 归零完成后,我们应该可以开始 Storyboard 的淡入。

例如:

单一动画class:

internal class SingleAnimations
{
    public static DoubleAnimation SetToZero(object sender)
    {
        var element = sender as UIElement;
        DoubleAnimation doubleAnimation = new DoubleAnimation();
        doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, 0);
        doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 0));
        doubleAnimation.From = 1;
        doubleAnimation.To = 0;
        Storyboard.SetTarget(doubleAnimation, element);
        Storyboard.SetTargetProperty(doubleAnimation, "Opacity");
        return doubleAnimation;

    }

    public static DoubleAnimation SimpleElementFadeIn(object sender, int fadeTime, int delay)
    {
        var element = sender as UIElement;
        DoubleAnimation doubleAnimation = new DoubleAnimation();
        doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, delay);
        doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, fadeTime));
        doubleAnimation.From = 0;
        doubleAnimation.To = 1;
        Storyboard.SetTarget(doubleAnimation, element);
        Storyboard.SetTargetProperty(doubleAnimation, "Opacity");
        return doubleAnimation;

    }

OpacityWithChildren_Light方法:

public static  void OpacityWithChildren_Light(object sender, int delay)
{
    var storyboardOfSetOpacityToZero = new Storyboard();
    var storyboardFadeIn = new Storyboard();
    UIElement rootElement = sender as UIElement;
    int childCount = VisualTreeHelper.GetChildrenCount(rootElement);
    if (childCount > 0)
    {
        for (int index = 0; index < childCount; index++)
        {
            UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index);
            var SetOpacityToZero = SingleAnimations.SetToZero(element);
            var SetOpacityToOne = SingleAnimations.SimpleElementFadeIn(element, 100, delay * index);
            storyboardOfSetOpacityToZero.Children.Add(SetOpacityToZero);
            storyboardFadeIn.Children.Add(SetOpacityToOne);
        }
        storyboardOfSetOpacityToZero.Begin();
        storyboardOfSetOpacityToZero.Completed += (s, e) => { storyboardFadeIn.Begin(); };
    }
}