WPF: Можно ли поместить цветную анимацию в стиль? - PullRequest
3 голосов
/ 05 декабря 2009

Это простое окно WPF в 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>

Обратите внимание, что это стиль. Что мы можем сделать со стилем? Это App.xaml, который дает светло-голубой фон

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

Чтобы сделать его более сложным, это фон с голубым градиентным фоном:

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

Последний шаг, который я хочу сделать, это анимировать этот цвет. У меня

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

Так что я могу сделать это в конструкторе Window:

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

Но я получаю исключение:

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

Я пробовал различные комбинации значений для свойств анимации Storyboard.TargetName и Storyboard.TargetProperty, но они не работали, я просто нащупываю в темноте. Лучший результат - применить стиль, анимацию и все к любому окну без какого-либо или с минимальным кодом C #

.

Обновление: вот рабочий App.xaml, основанный на ответе itowlson:

<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 Ответ

4 голосов
/ 05 декабря 2009

У вас нет ничего с именем "(UIElement)", поэтому TargetName не разрешается. Документы для Storyboard.Begin (FrameworkElement) гласят: «Анимации без TargetName применяются к withObject », поэтому вы должны просто отключить TargetName, и анимация будет применена к Background.GradientStops. [1]. Цвет окна, через которое вы проходите.

В качестве альтернативы, чтобы избежать необходимости в выделении кода, почему бы не использовать EventTrigger в вашем стиле для запуска раскадровки? См. Документацию EventTrigger в MSDN для примера.

...