Reputation: 21855
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.
Upvotes: 4
Views: 5011
Reputation: 21855
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" >
Upvotes: 2
Reputation: 21855
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" />
Upvotes: 1
Reputation: 10604
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>
Upvotes: 1