第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > WPF中的Behavior及Behavior在MVVM模式下的应用

WPF中的Behavior及Behavior在MVVM模式下的应用

时间:2022-11-02 12:18:25

相关推荐

WPF中的Behavior及Behavior在MVVM模式下的应用

WPF中的Behavior及Behavior在MVVM模式下的应用

在WPF中,Behaviors(行为)是一种可重用的组件,可以附加到任何UI元素上,以添加特定的交互行为或功能。Behaviors可以通过附加属性或附加行为的方式来实现。

Behavior并不是WPF组件中的内容,需要安装nuget包,使用行为需要nuget安装Microsoft.Xaml.Behaviors.Wpf,FrameWork版本安装System.Windows.Interactivity.WPF,同时添加命名空间xmlns:i="/xaml/behaviors"

使用Interaction.Behaviors

<BorderWidth="100"Height="100"Background="Red"><!--直接使用Behavior实现可拖拽Border--><i:Interaction.Behaviors><i:MouseDragElementBehavior /></i:Interaction.Behaviors></Border>

官方内置了以下几种Behavior,可以根据需要使用。

自定义Behavior

可以根据需要,自定义Behavior,下面是一个鼠标触发MouseEnter事件改变背景色的Behavior

class MyBehavior:Behavior<Border>//必须制定泛型类型,因为某些属性是针对特定类型的{//要重写两个方法//OnAttached()表示当挂载到对应的对象上的时候触发//OnDetaching()在对象销毁时触发protected override void OnAttached(){//AssociatedObject表示关联的对象AssociatedObject.MouseEnter += (_, _) => AssociatedObject.Background = Brushes.Orange;}protected override void OnDetaching(){base.OnDetaching();}}

<BorderWidth="100"Height="100"Background="Red"><!--可以应用多个Behavior--><i:Interaction.Behaviors><i:MouseDragElementBehavior /><local:MyBehavior /></i:Interaction.Behaviors></Border>

案例:实现自动清空文本框内容

class ClearTextBehavior : Behavior<Button>{//依赖属性,制定清空哪个文本框public TextBox Target{get {return (TextBox)GetValue(TargetProperty); }set {SetValue(TargetProperty, value); }}public static readonly DependencyProperty TargetProperty =DependencyProperty.Register("Target", typeof(TextBox), typeof(ClearTextBehavior), new PropertyMetadata(null));protected override void OnAttached(){AssociatedObject.Click += AssociatedObject_Click;}private void AssociatedObject_Click(object sender, RoutedEventArgs e){Target?.Clear();}protected override void OnDetaching(){AssociatedObject.Click -= AssociatedObject_Click;}}

<TextBox x:Name="tbx" /><Button Width="30" Content="清空"><i:Interaction.Behaviors><local:ClearTextBehavior Target="{Binding ElementName=tbx}" /></i:Interaction.Behaviors></Button>

使用Interaction.Triggers

使用EnentTrigger实现点击button关闭整个窗口

<Button Content="Close"><i:Interaction.Triggers><i:EventTrigger EventName="Click"><!--一定要设置TargetObject不然默认的对象为dataContext--><i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" /></i:EventTrigger></i:Interaction.Triggers></Button>

同样,可以应用多个Trigger

<Button Content="Close"><i:Interaction.Triggers><i:EventTrigger EventName="Click"><i:CallMethodAction MethodName="Close" TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" /></i:EventTrigger><!--实现鼠标悬浮后改变颜色--><i:DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=IsMouseOver}" Value="True"><i:ChangePropertyActionPropertyName="Background"TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Button}}"Value="Red" /></i:DataTrigger></i:Interaction.Triggers></Button>

还可以使用Command与VM绑定

<Button Width="150" Height="50" Content="Interaction.Triggers"><i:Interaction.Triggers><i:EventTrigger EventName="Click"><i:InvokeCommandAction Command="{Binding myCommand}" /></i:EventTrigger></i:Interaction.Triggers></Button>

官方内置了以下几种Trigger,可以根据需要使用。

Style中的Trigger和控件中的Trigger

Style中的各种Trigger参见WPF的Style

继承自FrameworkElement类中控件也可以直接使用trigger

<ButtonWidth="150"Height="100"Content="Button.Triggers"><Button.Triggers><EventTrigger RoutedEvent="MouseEnter"><BeginStoryboard><Storyboard><ColorAnimationStoryboard.TargetProperty="(Button.Background).(SolidColorBrush.Color)"To="Red"Duration="0:0:0:5" /></Storyboard></BeginStoryboard></EventTrigger></Button.Triggers></Button>

可以看出无论是Style中的Trigger还是控件下面的Trigger,都是使用的RoutedEvent属性来设置事件,但是有些事件是不属于RoutedEvent的,比如listbox的选择某个条目事件。而且这两种Trigger都是对故事板进行操作。

MVVM模式来实现获得鼠标的坐标

当鼠标在窗口上移动时,将坐标信息传到VM中,并在V中显示。那有人会问,这样还不如直接不经过VM直接在V中进行显示,关键在于,某些时候VM中需要坐标信息,而且要遵循MVVM模式。

自定义Behavior

class PositionBehavior : Behavior<Window>{//设置两个依赖属性public double X{get {return (double)GetValue(XProperty); }set {SetValue(XProperty, value); }}public static readonly DependencyProperty XProperty =DependencyProperty.Register("X", typeof(double), typeof(PositionBehavior), new FrameworkPropertyMetadata(0.0,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));public double Y{get {return (double)GetValue(YProperty); }set {SetValue(YProperty, value); }}public static readonly DependencyProperty YProperty =DependencyProperty.Register("Y", typeof(double), typeof(PositionBehavior), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));protected override void OnAttached(){AssociatedObject.MouseMove += AssociatedObject_MouseMove;}private void AssociatedObject_MouseMove(object sender, MouseEventArgs e){var pos = e.GetPosition(this.AssociatedObject);X = pos.X;Y = pos.Y;}protected override void OnDetaching(){AssociatedObject.MouseMove -= AssociatedObject_MouseMove;}}

VM

class ViewModel1 : INotifyPropertyChanged{private double x;private double y;public double X{get {return x; }set{x = value;PropertyChanged.Invoke(this, new PropertyChangedEventArgs("X"));PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Position"));}}public double Y{get {return y; }set{y = value;PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Y"));PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Position"));}}public string Position{get {return $"坐标为:{X:F2},{Y:F2}"; }}public event PropertyChangedEventHandler? PropertyChanged;}

View

<Window......xmlns:i="/xaml/behaviors"><!--双向模式绑定VM中的X,Y--><i:Interaction.Behaviors><local:PositionBehavior X="{Binding X}" Y="{Binding Y}"/></i:Interaction.Behaviors><StackPanel Orientation="Vertical"><TextBox x:Name="tbx" FontSize="30" Text="{Binding Position,Mode=OneWay}" /></StackPanel></Window>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。