使用 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.Opacity
将Opacity
设置为0。当 Storyboard
的 Opacity
归零完成后,我们应该可以开始 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(); };
}
}
查看发生了什么的一些代码:
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.Opacity
将Opacity
设置为0。当 Storyboard
的 Opacity
归零完成后,我们应该可以开始 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(); };
}
}