1

I have a DataGrid which contains a list of item that implement a boolean property called ResultChanged, this property allow me to create a blink effect on a particular cell of the DataGrid, in particular, if the property is setted to true then the cell of the DataGrid will colored by orange and blinking for 5 seconds, at the end of the animation, the color will keeped on the DataGrid and this working well for me, except for one problem.

Problem

When I click on the DataGrid (any rows) the color applied by the animation will be removed, but I want that such color remain on the cell.

This is my code:

<DataGridTextColumn Header="{DynamicResource hour}" Binding="{Binding Result}">
<DataGridTextColumn.CellStyle>
  <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource MaterialDesignDataGridCell}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding ResultChanged}" Value="True" >
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <Storyboard x:Name="Blink" 
                                    AutoReverse="True" 
                                    RepeatBehavior="5x">
                            <ColorAnimationUsingKeyFrames BeginTime="00:00:00"
                                Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                                <EasingColorKeyFrame KeyTime="00:00:01" 
                                                     Value="Orange" />
                            </ColorAnimationUsingKeyFrames>
                            <ColorAnimationUsingKeyFrames 
                                BeginTime="00:00:00"
                                Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)">
                                <EasingColorKeyFrame KeyTime="00:00:01" 
                                                     Value="Black" />
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                        <Storyboard AutoReverse="False">
                            <ColorAnimationUsingKeyFrames BeginTime="00:00:10" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
                                <EasingColorKeyFrame KeyTime="00:00:01" Value="Orange" />
                            </ColorAnimationUsingKeyFrames>
                        </Storyboard>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
    </Style.Triggers>
  </Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>

someone know what I did wrong?

Charanoglu
  • 1,229
  • 2
  • 11
  • 30

1 Answers1

1

The animation's effects will be lost when you select or unselect the row affected by the animation, because DataGrid changes the foreground and background brushes of the selected row. Now, normally, the animation's changes to the Foreground and Background properties would have precedence over those changes for the selected row. But your animation does not animate Foreground and Background! Instead, it animates Foreground.Color and Background.Color; these changes have no precedence and will be lost when something else changes Foreground or Background directly.

Therefore, your animation must animate Foreground and Background directly. Then, the changes will remain in effect even after the animation has ended.

You could achieve this, for example, by using the BrushAnimation class from the answer in question Brush to Brush Animation and using a storyboard similar to this:

<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
    <DataTrigger.EnterActions>
        <BeginStoryboard>
            <Storyboard>
                <Storyboard x:Name="Blink" 
                            RepeatBehavior="5x">
                    <local:BrushAnimation Storyboard.TargetProperty="Background" 
                                            BeginTime="00:00:00" Duration="0:0:0.5" From="White" To="Orange" />
                    <local:BrushAnimation Storyboard.TargetProperty="Foreground" 
                                            BeginTime="00:00:00" Duration="0:0:0.5" From="Yellow" To="Black" />
                </Storyboard>
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.EnterActions>
</DataTrigger>

EDIT:

Here is a solution that allows AutoReverse to be set to true:

<DataTrigger Binding="{Binding ResultChanged}" Value="True" >
    <DataTrigger.EnterActions>
        <BeginStoryboard>
            <Storyboard>
                <!-- The next two animations will take 10 seconds: -->
                <Storyboard x:Name="Blink" AutoReverse="True" RepeatBehavior="5x">
                    <local:BrushAnimation Storyboard.TargetProperty="Background" 
                                            BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
                    <local:BrushAnimation Storyboard.TargetProperty="Foreground" 
                                            BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
                </Storyboard>
                <!-- Same animations as above, but BeginTime offset by 10 seconds and neither repeat nor auto reverse: -->
                <Storyboard x:Name="finalBlink" BeginTime="00:00:10">
                    <local:BrushAnimation Storyboard.TargetProperty="Background" 
                                            BeginTime="00:00:00" Duration="0:0:1" From="White" To="Orange"/>
                    <local:BrushAnimation Storyboard.TargetProperty="Foreground" 
                                            BeginTime="00:00:00" Duration="0:0:1" From="Yellow" To="Black"/>
                </Storyboard>
            </Storyboard>
        </BeginStoryboard>
    </DataTrigger.EnterActions>
</DataTrigger>
FrankM
  • 1,007
  • 6
  • 15
  • `local` is the namespace in which you have added the code for `BrushAnimation`. E.g. if the C# namespace is called `WpfApplication12`, then you would have to add the declaration `xmlns:local="clr-namespace:WpfApplication12"` at the top of your XAML. Of course, you can use another name than `local`. – FrankM Jul 08 '18 at 11:15
  • is possible slow down the speed of the animation? how? – Charanoglu Jul 08 '18 at 13:29
  • 1
    @Charanoglu Set a larger value to the `Duration` properties, e.g. `Duration="0:0:2"` would be two seconds. – FrankM Jul 08 '18 at 13:30
  • is possible set a fade in effect? I tried auto reverse and this works but I got again the bug of the question... – Charanoglu Jul 08 '18 at 13:58