在控制模板资源中挂钩故事板的完成事件
本文关键字:故事 事件 控制 资源 | 更新日期: 2023-09-27 18:08:06
我正在创建一个自定义控件ImageFader。样式模板看起来像这样:
<ControlTemplate TargetType="{x:Type controls:ImageFader}">
<Grid>
<Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stretch="{TemplateBinding Stretch}"
x:Name="PART_SourceImage" Opacity="1" />
<Image HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stretch="{TemplateBinding Stretch}"
x:Name="PART_TargetImage" Opacity="0" />
</Grid>
<ControlTemplate.Resources>
<Storyboard x:Key="FadeImageStoryboard">
<!-- fade in the new image -->
<DoubleAnimation From="0" To="1"
Duration="{TemplateBinding FadeTime}"
Storyboard.TargetName="PART_TargetImage"
Storyboard.TargetProperty="Opacity" />
<!-- fade out the previous image -->
<DoubleAnimation From="1" To="0"
Duration="{TemplateBinding FadeTime}"
Storyboard.TargetName="PART_SourceImage"
Storyboard.TargetProperty="Opacity" />
</Storyboard>
</ControlTemplate.Resources>
</ControlTemplate>
在代码中,我有这样的:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SourceImage = Template.FindName("PART_SourceImage", this) as Image;
TargetImage = Template.FindName("PART_TargetImage", this) as Image;
FadeImageStoryboard = Template.Resources["FadeImageStoryboard"] as Storyboard;
FadeImageStoryboard.Completed += new EventHandler(FadeImageStoryboard_Completed);
}
在完成的处理程序中,我试图交换图像并重置其不透明度:
private void FadeImageStoryboard_Completed(object sender, EventArgs e)
{
SourceImage.Source = TargetImage.Source;
SourceImage.Opacity = 1;
TargetImage.Opacity = 0;
}
我在DispatchTimer中使用如下方式开始动画:
FadeImageStoryboard.Begin(this, this.Template, true);
一切都很好,直到我把两个或更多的ImageFader控件在同一个窗口。当我这样做时(使用DispatchTimer以不同的间隔开始动画),故事板完成事件为两个imagefader运行。
我相信我的控件正在从模板资源中获取故事板作为静态引用。
如何避免这种情况?
一个解决方案可以从代码中创建故事板,它不会变得太丑:)
只需更改下面的代码:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SourceImage = Template.FindName("PART_SourceImage", this) as Image;
TargetImage = Template.FindName("PART_TargetImage", this) as Image;
FadeImageStoryboard = GetFadeImageStoryboard();
FadeImageStoryboard.Completed += new EventHandler(FadeImageStoryboard_Completed);
}
private Storyboard GetFadeImageStoryboard()
{
DoubleAnimation fadeNewImage = new DoubleAnimation { From = 0, To = 1, Duration = FadeTime };
Storyboard.SetTarget(fadeNewImage, SourceImage);
Storyboard.SetTargetProperty(fadeNewImage, new PropertyPath("Opacity"));
DoubleAnimation fadePreviousImage = new DoubleAnimation { From = 0, To = 1, Duration = FadeTime };
Storyboard.SetTarget(fadePreviousImage, TargetImage);
Storyboard.SetTargetProperty(fadePreviousImage, new PropertyPath("Opacity"));
Storyboard fadeImageStoryboard = new Storyboard();
fadeImageStoryboard.Children.Add(fadeNewImage);
fadeImageStoryboard.Children.Add(fadePreviousImage);
return fadeImageStoryboard;
}
每个控件都会得到它自己的Storyboard。我不认为把这些故事板作为模板的一部分是一个好主意,因为它们是这个控件正确行为的重要组成部分,而且也没有太多的东西要改变(所以在几乎所有的模板中代码都必须重复)。