0
votes

I have a Border control and when the mouse is clicked on it I would like the Border's background to turn green momentarily if the "IsLeft" property from my view model is true. If "IsLeft" is false, I would like the background to turn red momentarily.

I have one storyboard for the green animation, and a second storyboard for the red animation.

I think I need to combine an EventTrigger (for the mouse click) and DataTrigger (bound to IsLeft) to do this, but I'm not sure how.

Note that I also have an MVVM Relay Command to perform some logic in the ViewModel when the border is clicked.

<Window x:Class="WpfTestBase.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfTestBase"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:Custom="http://www.galasoft.ch/mvvmlight"
    xmlns:h="clr-namespace:WpfTestBase.Helpers"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding Path=Main, Source={StaticResource Locator}}">
<Window.Resources>
    <Storyboard x:Key="StoryboardCorrect">
        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.IsEnabled)">
            <DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
            <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="True"/>
        </BooleanAnimationUsingKeyFrames>
        <ColorAnimationUsingKeyFrames Duration="0:0:0.5" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
            <DiscreteColorKeyFrame KeyTime="0:0:0" Value="#00FF00"/>
            <DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="LightBlue"/>
        </ColorAnimationUsingKeyFrames>
        <h:CommandFakeAnimation Duration="0:0:0" Command="{Binding Path=FakeAnimationCommand, Mode=OneWay}"
                                        Storyboard.TargetProperty="Opacity" />
    </Storyboard>
    <Storyboard x:Key="StoryboardWrong">
        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.IsEnabled)">
            <DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
            <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="True"/>
        </BooleanAnimationUsingKeyFrames>
        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
            <DiscreteColorKeyFrame KeyTime="0:0:0" Value="#FF0000"/>
            <DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="LightBlue"/>
        </ColorAnimationUsingKeyFrames>
        <h:CommandFakeAnimation Duration="0:0:0" Command="{Binding Path=FakeAnimationCommand, Mode=OneWay}"
                                        Storyboard.TargetProperty="Opacity" />
    </Storyboard>
</Window.Resources>
<Canvas>
    <Viewbox Canvas.Left="025" Canvas.Top="57">
        <Border x:Name="border" Width="200" Height="82" Canvas.Left="098" Canvas.Top="93" BorderThickness="6,8,7,8" 
                BorderBrush="Black" Background="LightBlue">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <Custom:EventToCommand Command="{Binding BorderCommand, Mode=OneWay}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <Border.Triggers>
                <EventTrigger RoutedEvent="Border.MouseLeftButtonUp">
                    <BeginStoryboard Storyboard="{StaticResource StoryboardCorrect}"/>
                </EventTrigger>
            </Border.Triggers>
            <TextBlock Text="{Binding CountModel.Word}"/>
        </Border>
    </Viewbox>
    <TextBlock x:Name="textBlock1" Canvas.Left="312" TextWrapping="Wrap" Text="IsLeft:" Canvas.Top="188"/>
    <TextBlock x:Name="textBlock2" Canvas.Left="348" TextWrapping="Wrap" Text="{Binding IsLeft}" Canvas.Top="188"/>

</Canvas>

1

1 Answers

1
votes

Instead of dynamically selecting a Storyboard, you can use a single Storyboard but bind your DiscreteColorKeyFrame.Value DependencyProperty to your IsLeft property and then use an IValueConverter to convert the value to the appropriate color.

The converter would look something like this:

[ValueConversion(typeof(bool), typeof(System.Windows.Media.Color))]
public class IsLeftToColorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((bool)value) ? System.Windows.Media.Color.Green : System.Windows.Media.Color.Red
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Your XAML could then look something like this:

    <Border x:Name="border" Width="200" Height="82" Canvas.Left="098" Canvas.Top="93" BorderThickness="6,8,7,8" 
            BorderBrush="Black" Background="LightBlue">
        <Border.Triggers>
            <EventTrigger RoutedEvent="Border.MouseLeftButtonUp">
                <BeginStoryboard>
                    <Storyboard>
                        <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.IsEnabled)">
                            <DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
                            <DiscreteBooleanKeyFrame KeyTime="0:0:0.5" Value="True"/>
                        </BooleanAnimationUsingKeyFrames>
                        <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
                            <DiscreteColorKeyFrame KeyTime="0:0:0" Value="{Binding IsLeft, Converter={StaticResource IsLeftToColorConverter}}"/>
                            <DiscreteColorKeyFrame KeyTime="0:0:0.5" Value="LightBlue"/>
                        </ColorAnimationUsingKeyFrames>
                        <h:CommandFakeAnimation Duration="0:0:0" Command="{Binding Path=FakeAnimationCommand, Mode=OneWay}"
                                    Storyboard.TargetProperty="Opacity" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Border.Triggers>
        <TextBlock Text="{Binding CountModel.Word}"/>
    </Border>