Question

I'm using <i:EventTrigger> to play a storyboard animation that changes the foreground of a label. (I need to use this type of trigger because I'm using its SourceObject property in order to bind to the datacontext's event. I removed the binding from the example for simplicity).
When this animation ends, I want to change the label back to its original color (blue), but not in the code-behind because I'm using MVVM. (I'm familiar with the Completed event of the storyborad, but I can't use it because it demends code behind and breaks the MVVM pattern.)

This is my code:

<Window x:Class="WpfApplication12.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.Resources>
        <Storyboard x:Key="MySB" Storyboard.TargetProperty="Foreground">
            <DoubleAnimation Storyboard.TargetName="GradientStop2"
                            Storyboard.TargetProperty="Offset"
                            From="0.0" To="0.6" Duration="0:0:0.6" RepeatBehavior="0:0:3"
                            AutoReverse="True" />
            <DoubleAnimation Storyboard.TargetName="GradientStop3"
                            Storyboard.TargetProperty="Offset"
                            From="0.4" To="1" Duration="0:0:0.6" RepeatBehavior="0:0:3"
                            AutoReverse="True" />
        </Storyboard>
    </Grid.Resources>
    <Label x:Name="CollectionTabHeader" Foreground="Blue" Height="30" Width="80">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseEnter">
                    <ei:ChangePropertyAction PropertyName="Foreground">
                        <ei:ChangePropertyAction.Value>
                            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                <GradientStop x:Name="GradientStop1" Color="Red" Offset="0.0" />
                                <GradientStop x:Name="GradientStop2" Color="White" Offset="0.2" />
                                <GradientStop x:Name="GradientStop3" Color="White" Offset="0.3" />
                                <GradientStop x:Name="GradientStop4" Color="Red" Offset="1.0" />
                            </LinearGradientBrush>
                        </ei:ChangePropertyAction.Value>
                    </ei:ChangePropertyAction>
                    <ei:ControlStoryboardAction Storyboard="{StaticResource MySB}"     
                                    ControlStoryboardOption="Play"/>
                </i:EventTrigger>
        </i:Interaction.Triggers>
        MyLabel
    </Label>
</Grid>

Was it helpful?

Solution

Firstly, there is nothing wrong with using the code behind to handle events when using MVVM. Secondly, even if you really don't want to use the code behind in these situations, then you can handle that event in an MVVM-friendly manner by implementing an Attached Property.

Rather than explaining the whole situation again in this question, I'd prefer to recommend that you read through my answer to the What's the best way to pass event to ViewModel? question here on Stack Overflow. It contains a full code example and although it deals with a different event, that makes little difference... just replace the GetPreviewKeyDown event with your Completed event instead.

OTHER TIPS

Eliminating code behind with MVVM pattern is not an end in itself - it's just side effect (good one although). Purpose of Model-View-ViewModel is: eliminate mixing of application logic and view code - so application could be testable (and code a bit more reusable). There is nothing wrong about code-behind view-related code which doesn't affect application logic / data manipulation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top