在控制模板资源中挂钩完成故事板事件的问题

时间:2011-09-07 15:33:06

标签: c# wpf xaml wpf-controls

我正在创建一个名为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以不同的间隔启动动画),两个ImageFaders的故事板完成事件运行。

我相信我的控制权是将模板资源中的故事板作为静态参考。

我该如何避免这种情况?

1 个答案:

答案 0 :(得分:2)

一个解决方案可能是从代码创建故事板,它不会太难看:)

只需更改此代码:

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;
}

每个控件都会获得它自己的故事板。我不认为将这些故事板作为模板的一部分是一个好主意,因为它们是这种控制的正确行为的一个重要部分,并且也没有太多东西可以改变它们(所以在几乎所有代码必须重复的模板。)

相关问题