在WPF中,假如我们需要给Button增加阴影效果,同时又需要给TextBlock增加阴影效果,或者又来了新的需求,连DataGrid也需要增加阴影效果。虽然我们已经学过如何给一个控件增加阴影效果,那就是在UIElement基类中去设置Effect属性,但是,每个控件都要单独去实现一次阴影效果,未免太繁琐。那又该如何偷懒呢?Behavior类(行为)就是专门用来实现这类需求的。
一句话,行为就是某些控件的共同特征的实现。如上所示,既然所有控件都有Effect属性,那干脆将这个特征写成一个行为,哪个控件有这个需求,直接调用这个行为即可。说是调用行为,专业点说,是将这个行业附加到某个控件上。
一、行为基类的定义
首先,我们来看一下Behavior基类的定义,了解大致组成后,我们才知道要怎么使用它。
namespace System.Windows.Interactivity
{
public abstract class Behavior : Animatable, IAttachedObject
{
protected Type AssociatedType { get; }
protected DependencyObject AssociatedObject { get; }
public void Attach(DependencyObject dependencyObject);
public void Detach();
protected override Freezable CreateInstanceCore();
protected virtual void OnAttached();
protected virtual void OnDetaching();
}
}
从定义上看,第一,它是一个抽象类,所以我们不能直接使用它,而是去继承它,在子类中实现我们自己的行业效果。第二,它继承于Animatable,说明行为是可以动画实现的。第三,它的命名空间为System.Windows.Interactivity,这个空间在哪里?
要使用行为,我们需要引入一个.dll动态库,或者您可以在nuget上找到它。请安装Microsoft.Xaml.Behaviors.Wpf这个组件包。
Behavior泛型基类
namespace System.Windows.Interactivity
{
public abstract class Behavior<T> : Behavior where T : DependencyObject
{
protected Behavior();
protected T AssociatedObject { get; }
}
}
其实,我们实际继承的是行为的泛型基类,因为WPF并不知道我们要给哪一种控件定义行为,于是,干脆提供一个泛型基类供我们使用。所以,我们将两个基类合并起来介绍。
AssociatedObject属性:这个属性通常表示一个控件,类型是DependencyObject(依赖对象),也就是说,我们写的行为要给某个控件使用的前提是,这个控件是一个DependencyObject(依赖对象)。
OnAttached():这是一个虚方法,将来在行为中被重写,表示附加一个行为时要执行的业务逻辑。
OnDetaching():这是一个虚方法,将来在行为中被重写,表示分离一个行为时要执行的业务逻辑。
二、行为的开发
接下来,我们假如要给一个TextBlock文字块增加一个阴影效果。那么,就可以编写一个自定义行为TextBehavior,相关代码如下:
public class TextBehavior : Behavior<TextBlock>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseEnter += AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave += AssociatedObject_MouseLeave;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter;
AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave;
}
private void AssociatedObject_MouseEnter(object sender,
System.Windows.Input.MouseEventArgs e)
{
var element = sender as TextBlock;
DropShadowEffect effect = new DropShadowEffect();
effect.Color = Colors.Gold;
effect.ShadowDepth = 0;
effect.BlurRadius = 15;
element.Effect = effect;
}
private void AssociatedObject_MouseLeave(object sender,
System.Windows.Input.MouseEventArgs e)
{
var element = sender as TextBlock;
DropShadowEffect effect = new DropShadowEffect();
effect.Color = Colors.Gold;
effect.ShadowDepth = 0;
effect.BlurRadius = 15;
element.Effect = null;
}
}
在上面的代码中, 我们给AssociatedObject的MouseEnter和MouseLeave分别订阅了两个事件回调函数,在回调函数中去设置DropShadowEffect 效果。注意,这里的AssociatedObject实际上就等于TextBlock控件哦。
在定义好一个行为后,接下来就是在XAML中使用它。
第一步,在XAML中导入命名空间 xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
第二步,编写前端XAML代码,引用TextBehavior行为,完整代码如下:
<Window x:Class="HelloWorld.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:HelloWorld"
xmlns:controls="clr-namespace:HelloWorld.Controls"
xmlns:helper="clr-namespace:HelloWorld.MVVM"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:behavior="clr-namespace:HelloWorld.Behaviors"
mc:Ignorable="d" Background="DarkCyan"
Title="WPF中文网 - 行为 - www.wpfsoft.com" Height="350" Width="500">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Canvas>
<TextBlock Text="WPF中文网"
Foreground="White"
FontSize="60"
Canvas.Left="92"
Canvas.Top="75">
<i:Interaction.Behaviors>
<behavior:TextBehavior/>
</i:Interaction.Behaviors>
</TextBlock>
<TextBlock Text="Behavior行为之阴影效果"
Foreground="White"
FontSize="40"
Canvas.Left="21"
Canvas.Top="182">
<i:Interaction.Behaviors>
<behavior:TextBehavior/>
</i:Interaction.Behaviors>
</TextBlock>
</Canvas>
</Window>
最后,运行调试,鼠标移上去,文字将增加阴影,鼠标移开,文字阴影将消失。
当前课程源码下载:(注明:本站所有源代码请按标题搜索)
文件名:106-《什么是行为》-源代码
链接:https://pan.baidu.com/s/1yu-q4tUtl0poLVgmcMfgBA
提取码:wpff
——重庆教主 2023年11月21日