事件起因
最近用wpf做了个小应用,主要有多个storyboard链接交互,其中还有传感器采集等待。最明显的表象就是前一个故事播放完成后,无法通过Visibility.Collapsed/Hidden
隐藏,通过搜索重新element.Visibility = new Visibility();
再隐藏也是无效。
尝试解决办法一
直接移除对象
Storyboard sb3 = this.Resources["Storyboard3"] as Storyboard;
sb3.Remove();
这个办法的确有效,但是只能对storyboard有效,如果是其它UI组件没法隐藏,因为多次执行而且还是异步的,导致比如要控制被事件控制过的组件,要点很多次才能执行到。
发现问题
通过在事件输出log发现,从第3个storyboard开始Completed事件开始以2的指数次执行
- 第3个storyboard+=Completed 执行 2 次
- 第4个storyboard+=Completed 执行 4 次
- 第5个storyboard+=Completed 执行 8 次
正确的方法
增加FillBehavior="Stop"
,意思是完播后停止,该属性默认参数是Holdon
意思是保持,在保持下无法修改storyboard控制的属性。
<Storyboard x:Key="Storyboard3" FillBehavior="Stop">
改成stop
后确实没有多次执行了,但是为什么呢?
参考代码
前台
<Page.Resources>
<Storyboard x:Key="Storyboard1">
</Storyboard>
<Storyboard x:Key="Storyboard2">
</Storyboard>
<Storyboard x:Key="Storyboard3" FillBehavior="Stop">
</Storyboard>
<Storyboard x:Key="Storyboard4" FillBehavior="Stop">
</Storyboard>
</Page.Resources>
后台
private void myMedia_MediaEnded(object sender, RoutedEventArgs e)
{
Console.WriteLine("播放结束");
Storyboard sb = this.Resources["Storyboard1"] as Storyboard;
sb.Completed += new EventHandler(StepOne);
sb.Begin();
}
}
private void StepOne(object sender, EventArgs e)
{
Task task = Task.Run( () =>
{
try
{
//异步
StepOneEnded();
}
});
}
private void StepOneEnded()
{
_synchronizationContext.Send(new SendOrPostCallback(s =>
{
Storyboard sb2 = this.Resources["Storyboard2"] as Storyboard;
sb2.Completed += new EventHandler(StepTwo);
sb2.Begin();
}), null);
}
private void StepTwo(object sender, EventArgs e)
{
Task task = Task.Run( () =>
{
try
{
// 异步
StepTwoEnded();
}
}
// 没有FillBehavior="Stop"这里会执行2次
private void StepTwoEnded()
{
_synchronizationContext.Send(new SendOrPostCallback(s =>
{
Storyboard sb3 = this.Resources["Storyboard3"] as Storyboard;
sb3.Completed += new EventHandler(StepThreeEnd);
sb3.Begin();
}), null);
}
private void StepThreeEnd(object sender, EventArgs e)
{
Storyboard sb4 = this.Resources["Storyboard4"] as Storyboard;
sb4.Completed += new EventHandler(StepFourEnd);
sb4.Begin();
}
// 没有FillBehavior="Stop"这里会执行4次
private void StepFourEnd(object sender, EventArgs e)
{
Console.WriteLine("sssssssssssss");
}
欢迎哪位同学解释一下?
这是我搜到的,也就是说没有clock就会多次触发事件?:
I do not think it is caused by propertychanged event, I find you remove the clock object in completed event, I think there is no need to remove it, if you want to stop it, you could set “FillBehavior=“Stop”” in xaml, I remove below code snippet, your sample works:
Storyboard sb = this.FindResource("FadeInFadeOutStoryboard") as Storyboard;
sb.Remove(StatusMessageBar);