Hi,@William Liu. Welcome Microsoft Q&A.
It's because you're using a Binding
in your Storyboard
. It can't be done because WPF attempts to freeze all the resources leveraged by a template for efficiency and when you use a Binding on a Freezable, in this case the Storyboard
, it prevents it from being able to be frozen.
You could try to refer to the following code.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0" Width="100">
<CheckBox x:Name="CheckBox" />
</Viewbox>
<bindingTest:MyBorder x:Name="MyBorder" Grid.Column="1" Background="Transparent" IsChecked="{Binding ElementName=CheckBox, Path=IsChecked}" OnBrush="Red">
</bindingTest:MyBorder>
</Grid>
MyBorder:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace BindingTest;
public class MyBorder : Border
{
public bool IsChecked
{
get => (bool)GetValue(IsCheckedProperty);
set => SetValue(IsCheckedProperty, value);
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register(nameof(IsChecked), typeof(bool), typeof(MyBorder), new PropertyMetadata(false, OnIsCheckedChanged));
public Color OnBrush
{
get => (Color)GetValue(OnBrushProperty);
set => SetValue(OnBrushProperty, value);
}
public static readonly DependencyProperty OnBrushProperty =
DependencyProperty.Register(nameof(OnBrush), typeof(Color), typeof(MyBorder), new PropertyMetadata(Colors.LightGreen, OnBrushChanged));
private static void OnIsCheckedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myBorder = (MyBorder)d;
if (myBorder.IsChecked)
{
var colorAnimation = new ColorAnimation
{
To = myBorder.OnBrush,
Duration = new Duration(TimeSpan.FromSeconds(3))
};
var storyboard = new Storyboard();
storyboard.Children.Add(colorAnimation);
Storyboard.SetTarget(colorAnimation, myBorder);
Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("(Background).(SolidColorBrush.Color)"));
storyboard.Begin();
}
else
{
var colorAnimation = new ColorAnimation
{
To = Colors.Transparent,
Duration = new Duration(TimeSpan.FromSeconds(1))
};
var storyboard = new Storyboard();
storyboard.Children.Add(colorAnimation);
Storyboard.SetTarget(colorAnimation, myBorder);
Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("(Background).(SolidColorBrush.Color)"));
storyboard.Begin();
}
}
private DispatcherTimer timer;
private static void OnBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myBorder = (MyBorder)d;
if (myBorder.IsChecked)
{
myBorder.AnimateColorChange((Color)e.OldValue, (Color)e.NewValue);
}
if (!myBorder.IsChecked)
{
myBorder.AnimateColorChange((Color)e.OldValue, (Color)Colors.Transparent);
}
}
private void AnimateColorChange(Color fromColor, Color toColor)
{
if (timer != null)
timer.Stop();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1);
timer.Tick += (sender, e) =>
{
timer.Stop();
var storyboard = new Storyboard();
var colorAnimation = new ColorAnimation(fromColor, toColor, new Duration(TimeSpan.FromSeconds(3)));
Storyboard.SetTarget(colorAnimation, this);
Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("(Background).(SolidColorBrush.Color)"));
storyboard.Children.Add(colorAnimation);
storyboard.Begin();
};
timer.Start();
}
}
The result:
If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.