Проблема в начале ColorAnimation для GradientStop в VisualState

У меня очень странная проблема с ColorAnimation. То, что я хочу сделать, довольно просто (как мне кажется): у меня есть Rectangle с GradientBrush в качестве фона. Этот прямоугольник имеет разные VisualState, которые изменяют цвета градиента. Хочу поставить анимацию перехода между состояниями. Моя проблема в том, что когда я меняю состояние, анимация начинается не с текущего цвета, а с цветом по умолчанию.

Вот фрагмент кода, который поможет вам воспроизвести это:

<Window x:Class="TestColorAnimation.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="350" Width="525">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition Height="30" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Rectangle Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" x:Name="rect">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualStateGroup.Transitions>
                    <VisualTransition GeneratedDuration="0:0:0.5"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="OrangeState">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetProperty="Color"
                                        Storyboard.TargetName="stop1"
                                        To="Orange" />
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="RedState">
                    <Storyboard>
                        <ColorAnimation Storyboard.TargetProperty="Color"
                                        Storyboard.TargetName="stop1"
                                        To="Red" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop x:Name="stop1" Color="LightGray" Offset="0" />
                <GradientStop x:Name="stop2" Color="LightGray" Offset="1" />
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>

    <Button Grid.Row="1" Grid.Column="0" Content="Go to orange"
     x:Name="orangeButton" Click="orangeButton_Click" />
    <Button Grid.Row="1" Grid.Column="1" Content="Go to red"
     x:Name="redButton" Click="redButton_Click" />
</Grid>
</Window>

Обработчики событий просто вызывают изменение состояния:

private void orangeButton_Click(object sender, RoutedEventArgs e)
{
    VisualStateManager.GoToElementState(this.rect, "OrangeState", true);
}

private void redButton_Click(object sender, RoutedEventArgs e)
{
    VisualStateManager.GoToElementState(this.rect, "RedState", true);
}

В этом случае, если я перейду в оранжевое состояние, анимация изменится с серого на оранжевый. Но затем, когда я перехожу в красное состояние, анимация меняет цвет с серого на красный. Я бы хотел (и ожидал), что цвет изменится с оранжевого на красный.

Я попытался использовать SolidColorBrush вместо LinearGradientBrush, и переходы происходят должным образом. Я также пробовал использовать раскадровки вне VisualStates (но с LinearGradientBrush), и это тоже работает, как ожидалось. Единственная ситуация, в которой я воспроизвел эту проблему, - это ситуация в примере: LinearGradientBrush и ColorAnimation в VisualState.

Я делаю что-то неправильно? Возможно ли то, что я хочу?


person Damien Chaib    schedule 27.03.2011    source источник


Ответы (1)


Анимация LinearGradients будет работать, если вы напрямую измените цель на GradientStop Color:

<VisualState x:Name="OrangeState">
    <Storyboard>
        <ColorAnimation 
            Storyboard.TargetProperty = "(Rectangle.Fill).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)"
            Storyboard.TargetName="rect"
            To="Orange" />
    </Storyboard>
</VisualState>
<VisualState x:Name="RedState">
    <Storyboard>
        <ColorAnimation 
            Storyboard.TargetProperty = "(Rectangle.Fill).(LinearGradientBrush.GradientStops)[0].(GradientStop.Color)"
            Storyboard.TargetName="rect"
            To="Red" />
    </Storyboard>
</VisualState>
person Gimno    schedule 27.03.2011
comment
Действительно, это так! Большое спасибо @Gimno! Я не совсем уверен, почему ... Это потому, что анимация должна ссылаться на объект, который имеет визуальные состояния? - person Damien Chaib; 27.03.2011
comment
К сожалению, я тоже не знаю ответа. Я редко использую VisualStateManager, поэтому сначала подумал, что приведенный выше пример должен сработать. - person Gimno; 27.03.2011
comment
Я понимаю. Мне было бы любопытно узнать, так как это не решило мою проблему в моем реальном приложении. (Этот код был всего лишь фрагментом для воспроизведения моей проблемы). Я пытаюсь сузить круг, чтобы воспроизвести это, но пока не получается. - person Damien Chaib; 28.03.2011
comment
Я отмечаю это как ответ, поскольку он решает проблему, указанную в моем вопросе, но я все еще ищу более полное объяснение ... - person Damien Chaib; 19.04.2011