4

Currently I have the following code to flash a DataGrid cell when it's value changes:

<TextBlock Background="White" Text={Binding Date, NotifyOnTargetUpdated=True} >
    <EventTrigger RoutedEvent="Binding.TargetUpdated" >
        <BeginStoryboard>
            <Storyboard>
                <ColorAnimation AutoReverse="True" From="#1F1F1F" To="#FFFF88" Duration="0:0:0.2" Storyboard.TargetProperty="Background.Color" FillBehavior="Stop" />
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</TextBlock>

Now I need to execute this animation only if a boolean value of the viewmodel is true. How can I accomplish this?

EDIT: Extended the sample

Thanks.

10
  • Any chance of a working sample? Commented Jun 7, 2012 at 16:41
  • Why DataTrigger isn't an option ? It's precisely what you ask for... Commented Jun 7, 2012 at 17:00
  • @dodsky do you mean why I use an EventTrigger instead of a DataTrigger? Commented Jun 7, 2012 at 17:11
  • @SoMoS Yes, I'm wondering. DataTrigger will trigger an action when your boolean value changes... Commented Jun 7, 2012 at 17:16
  • @dodsky it's not a boolean value, it's a DateTime value, the boolean is the one that controls if the animation has to be shown or not, the binded value it's a DateTime. Commented Jun 7, 2012 at 17:20

3 Answers 3

2

Thanks to XAML guy for his answer on another forum. This is the answer to the question, the solution is to use the following attached behaviour:

class AttachedBehaviours
{
    public static bool GetAllowTargetUpdated(DependencyObject obj)
    {
        return (bool)obj.GetValue(AllowTargetUpdatedProperty);
    }

    public static void SetAllowTargetUpdated(DependencyObject obj, bool value)
    {
        obj.SetValue(AllowTargetUpdatedProperty, value);
    }

    // Using a DependencyProperty as the backing store for AllowTargetUpdated.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AllowTargetUpdatedProperty =
        DependencyProperty.RegisterAttached("AllowTargetUpdated", typeof(bool), typeof(AttachedBehaviours), new UIPropertyMetadata(false, PropChanged));


    static void PropChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var ele = obj as FrameworkElement;
        var be = ele.GetBindingExpression(TextBlock.TextProperty);
        if (be == null) return;

        var b = be.ParentBinding;

        var newBinding = new Binding(b.Path.Path);
        newBinding.NotifyOnTargetUpdated = (bool)e.NewValue;

        ele.SetBinding(TextBlock.TextProperty, newBinding);
    }
}

And this is its usage from XAML:

<TextBlock Background="White" Text="{Binding Date}"  local:AttachedBehaviours.AllowTargetUpdated="{Binding EnableAnimations}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,10,0,0"  >
Sign up to request clarification or add additional context in comments.

Comments

1

Have you tried something like this:

<ControlTemplate.Triggers>
    <DataTrigger Value="false">
        <DataTrigger.EnterActions>
            <BeginStoryboard> 
            <Storyboard> 
                <ColorAnimation AutoReverse="True" From="#1F1F1F" To="#FFFF88" Duration="0:0:0.2" Storyboard.TargetProperty="Background.Color" FillBehavior="Stop" /> 
            </Storyboard> 
        </BeginStoryboard> 

       </DataTrigger.EnterActions>
    </DataTrigger>
</ControlTemplate.Triggers>

3 Comments

I need to fire the animation on value change, the value is not a boolean so I cannot compare the value with anything, that's why I use a EventTrigger.
@SoMoS Fire it for a specific value or just the value changing?
Just for the value changing to inform to the end user that the value changed with a flash
1

Well, this is how I solved the problem. Probably is one of the ugliest codes I ever wrote so feel free to propose something better.

I've created a converter that I bind to the duration using the boolean value that enables / disables the animation. Something like this:

class AnimationEnablerConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool enableAnimation = (bool)value;

        if (enableAnimation)
        {
            return new System.Windows.Duration(new TimeSpan(0, 0, 0, 0, 200));
        }
        else
        {
            return new System.Windows.Duration(new TimeSpan(0, 0, 0, 0, 0));
        }
    }

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

    #endregion
}

And the xaml:

<ColorAnimation AutoReverse="True" From="#1F1F1F" To="#FFFF88" Duration="{Binding IsAnimationEnabled, Converter={StaticResource anim2}}" Storyboard.TargetProperty="Background.Color" FillBehavior="Stop" />

1 Comment

Ou shit! This is not working either because freezable elements cannot be binded. I'm getting a 'Cannot freeze this Storyboard timeline tree for use across threads' error. WTF!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.