Adorner实现边框线条动画
在 WPF 中,
Adorner
是一种特殊的装饰层,能够在 UI 元素之上绘制视觉效果。常用于提供视觉反馈或装饰功能,例如焦点指示、拖放效果等。
自定义 Adorne 类
要创建自定义 Adorner
,需要继承 Adorner
类并重写 OnRender
方法。在 OnRender
方法中,您可以使用 DrawingContext
绘制自定义图形。
示例:创建带动画边框的 Adorner
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
public class AnimatedBorderAdorner : Adorner
{
private double _animationProgress;
private AnimationClock _animationClock;
public AnimatedBorderAdorner(UIElement adornedElement) : base(adornedElement)
{
StartAnimation();
}
private void StartAnimation()
{
DoubleAnimation animation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(2)));
animation.RepeatBehavior = RepeatBehavior.Forever;
//animation.AutoReverse = true;
animation.AutoReverse = false;
// Create a clock for the animation and start it
_animationClock = animation.CreateClock();
_animationClock.CurrentTimeInvalidated += (s, e) =>
{
if (_animationClock.CurrentProgress.HasValue)
{
_animationProgress = _animationClock.CurrentProgress.Value;
// Request a redraw
InvalidateVisual();
}
ApplyAnimationClock(AnimationProgressProperty, _animationClock);
};
}
public double AnimationProgress
{
get { return (double)GetValue(AnimationProgressProperty); }
set { SetValue(AnimationProgressProperty, value); }
}
// Using a DependencyProperty as the backing store for AnimationProgress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AnimationProgressProperty =
DependencyProperty.Register("AnimationProgress", typeof(double), typeof(AnimatedBorderAdorner), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
Rect adornedElementRect = new Rect(this.AdornedElement.RenderSize);
// Calculate the dash offset based on the animation progress
double dashOffset = - adornedElementRect.Width * _animationProgress;
// Create a new Pen object for each render
Pen pen = new Pen(Brushes.ForestGreen, 2);
FormattedText ft = new FormattedText("ON",
CultureInfo.CurrentCulture,
FlowDirection.RightToLeft,
new Typeface(new FontFamily("微软雅黑"), FontStyles.Normal, FontWeights.Bold, FontStretches.Normal),
8,
Brushes.Green,
96);
drawingContext.DrawText(ft, new Point(adornedElementRect.TopRight.X - 2, adornedElementRect.TopRight.Y));
pen.DashStyle = new DashStyle(new double[] {adornedElementRect.Width / 4, adornedElementRect.Width / 4}, dashOffset);
drawingContext.DrawRectangle(null, pen, adornedElementRect);
}
}
应用 Adorner
为了将 Adorner 应用到 UI 元素,需要获取该元素的 AdornerLayer
,然后添加或移除 Adorner
。
示例:在 ToggleButton
上应用 Adorner
private void ToggleButton_Click(object sender, RoutedEventArgs e)
{
ToggleButton toggleButton = sender as ToggleButton;
AdornerLayer layer = AdornerLayer.GetAdornerLayer(toggleButton);
if (layer != null)
{
Adorner[] adorners = layer.GetAdorners(toggleButton);
AnimatedBorderAdorner existingAdorner = adorners?.OfType<AnimatedBorderAdorner>().FirstOrDefault();
if (existingAdorner != null)
{
layer.Remove(existingAdorner);
}
else
{
layer.Add(new AnimatedBorderAdorner(toggleButton));
}
}
}
XAML 中定义 UI 元素
在 XAML 中,可以使用 AdornerDecorator
包裹目标 UI 元素,以确保 Adorner
能够正确显示。
示例:定义 ToggleButton
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<AdornerDecorator>
<ToggleButton Width="100" Height="50" Content="Toggle" Click="ToggleButton_Click"/>
</AdornerDecorator>
</Grid>
</Window>
重要属性和方法
- AdornerLayer:用于管理
Adorner
的层。可以通过AdornerLayer.GetAdornerLayer(UIElement)
方法获取。 - ApplyAnimationClock:将动画应用到
DependencyProperty
,以便在动画进度变化时触发重绘。 - InvalidateVisual:请求重绘
Adorner
。
关键点总结
- 创建自定义 Adorner:继承
Adorner
类,重写OnRender
方法。 - 添加动画:使用
DoubleAnimation
和AnimationClock
为Adorner
添加动画效果。 - 管理 Adorner:通过
AdornerLayer
添加或移除Adorner
。 - 确保视觉效果:在 XAML 中使用
AdornerDecorator
包裹目标 UI 元素。 - 性能优化:在
OnRender
方法中避免复杂计算和创建大量对象,尽量复用资源。
通过这些步骤和示例,您可以在 WPF 应用程序中创建和管理复杂的 Adorner,以实现丰富的视觉效果和用户交互。