共计 3350 个字符,预计需要花费 9 分钟才能阅读完成。
什么是行为(Behavior)
在WPF中,行为(Behaviors)是一种将可重用的交互功能附加到UI元素上的方式,而不需要修改元素本身的代码或创建子类,然后通过XAML将这些组件附加到控件上。
主要特点
封装交互逻辑:封装交互逻辑:
无需子类化:无需创建自定义控件即可扩展现有控件功能
XAML声明式使用:可以通过XAML直接附加到控件
松耦合:行为与它们附加到的控件之间是松耦合的
核心组件
Behavior:基类,其中T是行为可以附加到的控件类型
TriggerAction:用于定义在特定事件发生时执行的操作
TriggerBase:定义触发操作的触发器
Trigger介绍
包含一个或多个动作的对象,可根据某些刺激调用这些动作。一种非常常见的触发器是针对事件触发的触发器(EventTrigger)。其他例子可能包括在定时器上触发的触发器,或在抛出未处理异常时触发的触发器。
<Grid xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Grid>
Behavior介绍
行为没有调用的概念;它是附加到元素上的东西,用于指定应用程序应在何时做出响应
<Grid xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<i:Interaction.Behaviors>
<i:EventTrigger EventName="Loaded">
<local:MyGridBehavior Command="{Binding LoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Behaviors>
</Grid>
public class MyGridBehavior: Behavior < Grid > {
public ICommand Command {
get
{
return (ICommand) GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(MyGridBehavior));
/// <summary>
/// 附加
/// </summary>
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
Command?.Execute(null);
}
/// <summary>
/// 卸载
/// </summary>
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
}
实际使用场景使用
当我们开发WPF的时候,发现目标控件是没有Command的属性的,我们应该如何解决呢?
相信大家第一时间会用Microsoft.Xaml.Behaviors.Wpf里面的EventTrigger配合InvokeCommandAction解决问题,实际上这不是很好的解决办法,在某些情况其实是无法触发第一时间触发的,比如Selector里面的SelectionChanged方法,使用这个其实是不是理想的,我们应该使用Behavior来处理,这样就能解决
Behavior使用方法
- 创建SelectorBehavior类
- 使用Behavior创建一个SelectionChangedCommand依赖属性命令
- 新增SelectionChanged方法,触发SelectionChangedCommand
- AssociatedObject其实就是我们的目标控件Selector,我们可以为它创建新增任何它能提供的一些方法
public class SelectorBehavior : Behavior<Selector>
{
public ICommand SelectionChangedCommand
{
get { return (ICommand)GetValue(SelectionChangedCommandProperty); }
set { SetValue(SelectionChangedCommandProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectionChangedCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectionChangedCommandProperty =
DependencyProperty.Register(
"SelectionChangedCommand",
typeof(ICommand),
typeof(SelectorBehavior)
);
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += OnSelectionChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.SelectionChanged -= OnSelectionChanged;
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectionChangedCommand?.Execute(AssociatedObject.SelectedItem);
}
}
<ListView ItemsSource="{Binding Items}"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors">
<i:Interaction.Behaviors>
<local:SelectorBehavior SelectionChangedCommand="{Binding SelectionChangedCommand}" />
</i:Interaction.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我们可以发现,我们为ListView新增了一个支持选择的命令,这个命令可以为我们解耦,完全符合MVVM的方式,相当于在原生的控件上新增了一个依赖属性,但是可以完全剥离
总结
行为是WPF中实现MVVM模式时非常有用的工具,因为它们允许你将视图特定的交互逻辑与视图模型分离。