在我的WPF应用程序中,我有一个反馈控件,我希望在用户操作完成后显示(保存数据,删除...)。可见性设置为隐藏开始,样式设置为定义为资源的animateFadeOut样式(参见下文)。然后我想设置文本并控制Visibility在我的C#代码中可见,并让反馈控件显示消息并在5秒后淡出并保持隐藏状态(Visibility.Hidden)。
以下XAML在我第一次调用control.Visiblity = Visibility.Visible时工作,但控件第二次不再出现。我想这是因为动画仍然在运行,它可以控制反馈控制。然后我尝试将FillBehavior设置为“停止”,但这只是使控件再次可见,我想隐藏它。然后,使用FillBehavior =“Stop”,我尝试设置一个触发器“当Opacity = 0时,将Visibility设置为Hidden”。触发器似乎没有触发,动画完成后我再次看到了可视控件。
请帮助指出我在这里做错了什么。
或者,如果您可以建议一种更好的方法来显示一个在5秒后消失并且可以反复调用的控件,我将不胜感激。
谢谢!
<Style TargetType="{x:Type FrameworkElement}" x:Key="animateFadeOut"> <Style.Triggers> <Trigger Property="Visibility" Value="Visible"> <Trigger.EnterActions> <BeginStoryboard > <Storyboard> <DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:0.5"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> </Trigger> </Style.Triggers> </Style>
答案 0 :(得分:31)
问题是,在动画完成后,您的控件仍然具有Visibility = Visible,因此无法再次输入。
我宁愿使用完成整个事情的动画,首先显示控件,然后隐藏它。
<Storyboard x:Key="animate">
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="0:0:0.0" Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.2"/>
<DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:0.5"/>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:5.5" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Hidden</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
使用如下:
((Storyboard)FindResource("animate")).Begin(someControl);
答案 1 :(得分:15)
Liz对于Visibility仍然可见是正确的。 alpha-mouse也是正确的,您需要在某些时候将其设置为隐藏。但是如果你在动画完成之前将它设置回来就不会起作用:
MyControl.Visibility = System.Windows.Visibility.Visible;
MyControl.Visibility = System.Windows.Visibility.Hidden;
因为动画的优先级更高(MSDN)
您可以将其设置回Storyboard中的Hidden.Completed事件:
private void Show()
{
MyControl.Visibility = System.Windows.Visibility.Visible;
var a = new DoubleAnimation
{
From = 1.0,
To = 0.0,
FillBehavior= FillBehavior.Stop,
BeginTime = TimeSpan.FromSeconds(2),
Duration = new Duration(TimeSpan.FromSeconds(0.5))
};
var storyboard = new Storyboard();
storyboard.Children.Add(a);
Storyboard.SetTarget(a, MyControl);
Storyboard.SetTargetProperty(a, new PropertyPath(OpacityProperty));
storyboard.Completed += delegate { MyControl.Visibility = System.Windows.Visibility.Hidden; };
storyboard.Begin();
}
答案 2 :(得分:12)
这是我的工作。这会使控件再次进入和退出。我没有玩“可见性”,而是只使用“不透明度”来处理它。
感谢Kane在这篇文章中提供的原始代码:Fade any control using a WPF animation
Storyboard storyboard = new Storyboard();
TimeSpan duration = TimeSpan.FromMilliseconds(500); //
DoubleAnimation fadeInAnimation = new DoubleAnimation()
{ From = 0.0, To = 1.0, Duration = new Duration(duration) };
DoubleAnimation fadeOutAnimation = new DoubleAnimation()
{ From = 1.0, To = 0.0, Duration = new Duration(duration) };
fadeOutAnimation.BeginTime = TimeSpan.FromSeconds(5);
Storyboard.SetTargetName(fadeInAnimation, element.Name);
Storyboard.SetTargetProperty(fadeInAnimation, new PropertyPath("Opacity", 1));
storyboard.Children.Add(fadeInAnimation);
storyboard.Begin(element);
Storyboard.SetTargetName(fadeOutAnimation, element.Name);
Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath("Opacity", 0));
storyboard.Children.Add(fadeOutAnimation);
storyboard.Begin(element);
答案 3 :(得分:2)
我的上帝永远。看看这个,它解决了使用alpha将Visibility更改为'Visible'和'Hidden'时动画制作的问题,动画不会冻结。
using System.Windows;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
button.Visibility = Visibility.Hidden;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
button.Visibility = Visibility.Visible;
}
}
}
XAML:
<Window x:Class="WpfApplication4.MainWindow"
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"
xmlns:local="clr-namespace:WpfApplication4"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
<Style.Resources>
<Storyboard x:Key="FadeOut">
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" FillBehavior="Stop">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="0:0:1" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1" AutoReverse="False" />
</Storyboard>
<Storyboard x:Key="FadeIn">
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1" AutoReverse="False" />
</Storyboard>
</Style.Resources>
<Setter Property="Width" Value="120"></Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Visibility" Value="Hidden" />
<Condition Property="Opacity" Value="1" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="FadeInStoryboard" />
<BeginStoryboard Name="FadeOutStoryboard" Storyboard="{StaticResource FadeOut}" />
</MultiTrigger.EnterActions>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Visibility" Value="Visible" />
<Condition Property="Opacity" Value="0" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="FadeOutStoryboard" />
<BeginStoryboard Name="FadeInStoryboard" Storyboard="{StaticResource FadeIn}" />
</MultiTrigger.EnterActions>
</MultiTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="200,186,0,0" VerticalAlignment="Top" Width="75" Height="38" />
<Button x:Name="button1" Content="Hide it" HorizontalAlignment="Left" Margin="112,96,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
<Button x:Name="button2" Content="Show it" HorizontalAlignment="Left" Margin="200,96,0,0" VerticalAlignment="Top" Width="75" Click="button2_Click"/>
<Label x:Name="label" Content="{Binding ElementName=button, Path=Opacity}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<Label x:Name="label1" Content="{Binding ElementName=button, Path=Visibility}" HorizontalAlignment="Left" Margin="10,36,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
答案 4 :(得分:0)
这应该可以修复你的故事板。
但是,请记住,一旦动画完成,您的控件将完全不透明 - 不可见,但您的Visibility属性仍设置为Visible。因此,您必须确保将Visibility属性重置为隐藏或折叠到某处。
<Style TargetType="{x:Type FrameworkElement}" x:Key="animateFadeOut">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard Name="MyFadeEffect">
<Storyboard>
<DoubleAnimation BeginTime="0:0:5.0" Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="MyFadeEffect"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
答案 5 :(得分:0)
上面的所有答案都至少使用了某种 XAML 代码,我个人并不喜欢它(因为它非常令人困惑),所以我找到了一种使用一些简单的 C# 代码执行相同操作的方法:< /p>
int secs = 2; // How long the fade should take in seconds
for (int i = 99; i >= 0; i--)
{
someControl.Opacity = i / 100d;
await Task.Delay(secs * 10);
}
someControl.Visibility = Visibility.Hidden;
someControl.Opacity = 1;
您可以在任何 Control
上使用它。您还需要在方法签名中添加 async
修饰符。如果没有 await
操作符,您的 UI 在控件淡出时无法响应。
控件淡出后,您可以像这样使其再次可见:
someControl.Visibility = Visibility.Visible;
这种方法可能不是“最好的”,但肯定是最简单易懂的。