views:

434

answers:

1

This is a simple WPF window in XAML:

<Window x:Class="AnimateTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
        x:Name="MainWindow"
        Style="{StaticResource TestStyle}">
    <Grid>
    </Grid>
</Window>

Note that is has a style. What can we do with the style? This is the App.xaml that gives it a light blue background

<Application x:Class="AnimateTest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        <Style x:Key="TestStyle">
            <Setter Property="Window.Background" Value="AliceBlue" />
        </Style>
    </Application.Resources>
</Application>

To get more complex, this is the background that gives it a blue gradient background:

<Application x:Class="AnimateTest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        <LinearGradientBrush x:Key="BackgroundBrush"
            EndPoint="0.6,0.6" StartPoint="0,0">
            <GradientStop Color="#FFFFFFFF" Offset="0" />
            <GradientStop Color="#FFD0D0F0" Offset="1" />
        </LinearGradientBrush>
        <Style x:Key="TestStyle">
            <Setter Property="Window.Background" Value="{StaticResource BackgroundBrush}" />
        </Style>
    </Application.Resources>
</Application>

The last step that I want to do is to animate this colour. I have

<Application x:Class="AnimateTest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        <LinearGradientBrush x:Key="BackgroundBrush"
            EndPoint="0.6,0.6" StartPoint="0,0">
            <GradientStop Color="#FFFFFFFF" Offset="0" />
            <GradientStop Color="#FFD0D0F0" Offset="1" />
        </LinearGradientBrush>
        <Style x:Key="TestStyle">
            <Setter Property="Window.Background" Value="{StaticResource BackgroundBrush}" />
        </Style>
        <Storyboard x:Key="ThemeAnimation">
            <ColorAnimationUsingKeyFrames
            Storyboard.TargetName="(UIElement)"
            Storyboard.TargetProperty="Background.GradientStops[1].Color"
            Duration="0:0:10"
            RepeatBehavior="Forever">
                <ColorAnimationUsingKeyFrames.KeyFrames>
                    <LinearColorKeyFrame Value="#FFD0D0F0" KeyTime="0:0:0" />
                    <LinearColorKeyFrame Value="#FFF0D0F0" KeyTime="0:0:10" />
                </ColorAnimationUsingKeyFrames.KeyFrames>
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
    </Application.Resources>
</Application>

So I can do this in the Window constructor:

        object themeAnimationObject = this.FindResource("ThemeAnimation");
        Storyboard themeAnimation = themeAnimationObject as Storyboard;
        themeAnimation.Begin(this);

But I get an exception:

(UIElement)' name cannot be found in the name scope of 'AnimateTest.Window1'

I have tried various combinations of values for the animation's Storyboard.TargetName and Storyboard.TargetProperty properties, but they didn't work, I'm just groping in the dark. The best outcome would be able to apply the style, animations and all to any window without any, or with minimal c# code

Update: Here's the working App.xaml based on itowlson's answer:

<Application x:Class="AnimateTest.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        <LinearGradientBrush x:Key="BackgroundBrush"
            EndPoint="0.6,0.6" StartPoint="0,0">
            <GradientStop Color="#FFFFFFFF" Offset="0" />
            <GradientStop Color="#FFD0D0F0" Offset="1" />
        </LinearGradientBrush>
        <Style x:Key="TestStyle" TargetType="FrameworkElement">
            <Setter Property="Window.Background" Value="{StaticResource BackgroundBrush}" />
            <Style.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimationUsingKeyFrames
                                Storyboard.TargetProperty="Background.GradientStops[1].Color"
                                Duration="0:0:10"
                                RepeatBehavior="Forever"
                                AutoReverse="True">
                                <ColorAnimationUsingKeyFrames.KeyFrames>
                                    <LinearColorKeyFrame Value="#FFD0D0F0" KeyTime="0:0:0" />
                                    <LinearColorKeyFrame Value="#FFF0D0F0" KeyTime="0:0:10" />
                                </ColorAnimationUsingKeyFrames.KeyFrames>
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Application.Resources>
</Application>
+1  A: 

You don't have anything named "(UIElement)", so TargetName isn't resolving. The docs for Storyboard.Begin(FrameworkElement) say "Animations without a TargetName are applied to containingObject", so you should be able to just leave off the TargetName, and the animation will be applied to the Background.GradientStops[1].Color of the Window you're passing in.

Alternatively, to avoid the need for code-behind, why not use an EventTrigger in your Style to run the Storyboard? See the EventTrigger docs in MSDN for an example.

itowlson
Both suggestions work, thanks
Anthony