4
votes

I'm trying to fade a textblock in then out to show a success message in MVVM but I can't get it to fade out again. I looked at this: WPF MVVM Property Change Animation but don't really follow. here is the style:

 <Style TargetType="TextBlock" x:Key="fadeinout">
        <Style.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(TextBlock.Opacity)" From="0.0" To="1.0" Duration="0:0:5"/>
                        <DoubleAnimation Storyboard.TargetProperty="(TextBlock.Opacity)" From="1.0" To="0.0" Duration="0:0:5"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>

and in the view

<TextBlock Text="{Binding Path=SuccessMessage}" Style="{StaticResource fadeinout}"  Width="60"/>

in the view model, after the save I do:

SuccessMessage = "Success";

where SuccessMessage is a property with a setter that calls PropertyChanged. I think I want the text fixed to something like "Your save was successful" but in any case I want the viewmodel to be able to do something that makes the textblock fade in and then out again, and repeat if the user saves again. What do I need to do?

EDIT (I can't self answer for 8 hours): Had to add NotifyOnTargetUpdated to the binding and now it fades in and out:

 <TextBlock Text="{Binding SuccessMessage, NotifyOnTargetUpdated=True}" Style="{StaticResource fadeInOut}"

I've now got one TextBox as per Jakob's answer(but changed the EventTrigger to Binding.TargetUpdated), one TextBlock like the above and one TextBlock inline like this:

<TextBlock Text="{Binding SuccessMessage, NotifyOnTargetUpdated=True}" Opacity="0" x:Name="tbMessage" Width="60" HorizontalAlignment="Left">
        <TextBlock.Triggers>
            <EventTrigger RoutedEvent="Binding.TargetUpdated">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="tbMessage" Storyboard.TargetProperty="Opacity" To="1" BeginTime="0:0:0" Duration="0:0:1" />
                        <DoubleAnimation Storyboard.TargetName="tbMessage" Storyboard.TargetProperty="Opacity" To="0" BeginTime="0:0:3" Duration="0:0:1"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </TextBlock.Triggers>
    </TextBlock>

and all three fade in and out with each save. Weirdly the templated one lags slightly behind the other two despite using the same timings.

1

1 Answers

2
votes

Try setting DoubleAnimation.BeginTime. That way you postpone the starting time of the fadeout animation so that it will not start before the fadein has finished. In the following example the text is shown for 2 seconds before fading out:

<DoubleAnimation Storyboard.TargetProperty="(TextBlock.Opacity)" From="0.0" To="1.0" Duration="0:0:5" BeginTime="0:0:0" />
<DoubleAnimation Storyboard.TargetProperty="(TextBlock.Opacity)" From="1.0" To="0.0" Duration="0:0:5" BeginTime="0:0:7" />

Alternatively you can use AutoReverse but then you will not be able to control how long to show the text before fading out.


UPDATE:

There seems to be some problems getting fading with event triggers to work with TextBlock because TextBlock does not have any appropriate events you can use in a trigger. The following is a working example where I have used TextBox instead of TextBlock. You can always style a TextBox so that it looks like a TextBlock even though TextBlock is more lightweight:

<TextBox Text="{Binding SuccessMessage}" Opacity="0" x:Name="textBoxMessage" >
    <TextBox.Triggers>
        <EventTrigger RoutedEvent="TextBoxBase.TextChanged">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation 
                                Storyboard.TargetName="textBoxMessage" 
                                Storyboard.TargetProperty="Opacity"
                                To="1" 
                                BeginTime="0:0:0" Duration="0:0:1"
                                />
                    <DoubleAnimation 
                                Storyboard.TargetName="textBoxMessage" 
                                Storyboard.TargetProperty="Opacity"
                                To="0" 
                                BeginTime="0:0:3" Duration="0:0:1"
                                />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </TextBox.Triggers>
</TextBox>