时间:2021-05-20
在我们进行WPF开发应用程序的时候不可避免的要使用到事件,很多时候没有严格按照MVVM模式进行开发的时候习惯直接在xaml中定义事件,然后再在对应的.cs文件中直接写事件的处理过程,这种处理方式写起来非常简单而且不用过多地处理考虑代码之间是否符合规范,但是我们在写代码的时候如果完全按照WPF规范的MVVM模式进行开发的时候就应该将相应的事件处理写在ViewModel层,这样整个代码才更加符合规范而且层次也更加清楚,更加符合MVVM规范。
常规用法
通过在代码中引入System.Windows.Interactivity.dll,引入了这个dll后我们就能够使用这个里面的方法来将事件映射到ViewModel层了,我们来看看具体的使用步骤,第一步就是引入命名控件
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"另外还可以通过另外一种方式来引入命名空间,其实这两者间都是对等的。
xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity这里以TextBox的GetFocus和LostFocus为例来进行说明
<TextBox Text="CommandBinding"><i:Interaction.Triggers><i:EventTrigger EventName="LostFocus"><i:InvokeCommandAction Command="{Binding OnTextLostFocus}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/></i:EventTrigger><i:EventTrigger EventName="GotFocus"><i:InvokeCommandAction Command="{Binding OnTextGotFocus}"CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/></i:EventTrigger></i:Interaction.Triggers></TextBox>这个里面我们重点来看看这个InvokeCommandAction的代码结构
namespace System.Windows.Interactivity{public sealed class InvokeCommandAction : TriggerAction<DependencyObject>{public static readonly DependencyProperty CommandProperty;public static readonly DependencyProperty CommandParameterProperty;public InvokeCommandAction();public string CommandName { get; set; }public ICommand Command { get; set; }public object CommandParameter { get; set; }protected override void Invoke(object parameter);}}这里我们发现这里我们如果我们定义一个Command的话我们只能够在Command中获取到我们绑定的CommandParameter这个参数,但是有时候我们需要获取到触发这个事件的RoutedEventArgs的时候,通过这种方式就很难获取到了,这个时候我们就需要自己去扩展一个InvokeCommandAction了,这个时候我们应该怎么做呢?整个过程分成三步:
这个对象除了封装我们常规的参数外还封装了我们需要的EventArgs属性,有了这个我们就能将当前的事件的EventArgs传递进来了。
这个里面的重点是要重写基类中的Invoke方法,将当前命令通过反射的方式来获取到,然后在执行command.Execute方法的时候将我们自定义的ExCommandParameter传递进去,这样我们就能够在最终绑定的命令中获取到特定的EventArgs对象了。
注意这里需要首先引入自定义的interactive的命名空间,这个在使用的时候需要注意,另外在最终的Command订阅中EventArgs根据不同的事件有不同的表现形式,比如Loaded事件,那么最终获取到的EventArgs就是RoutedEventArgs对象,如果是TableControl的SelectionChanged事件,那么最终获取到的就是SelectionChangedEventArgs对象,这个在使用的时候需要加以区分。
System.Windows.Interactivity.dll中一个重要的扩展就是对Behavior的扩展,这个Behavior到底该怎么用呢?我们来看下面的一个例子,我们需要给一个TextBlock和Button增加一个统一的DropShadowEffect,我们先来看看最终的效果,然后再就具体的代码进行分析。
1 增加一个EffectBehavior
public class EffectBehavior : Behavior<FrameworkElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.MouseEnter += AssociatedObject_MouseEnter; AssociatedObject.MouseLeave += AssociatedObject_MouseLeave; } private void AssociatedObject_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) { var element = sender as FrameworkElement; element.Effect = new DropShadowEffect() { Color = Colors.Transparent, ShadowDepth = 2 }; ; } private void AssociatedObject_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) { var element = sender as FrameworkElement; element.Effect = new DropShadowEffect() { Color = Colors.Red, ShadowDepth = 2 }; } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter; AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave; } }这里我们继承自System.Windows.Interactivity中的Behavior<T>这个泛型类,这里我们的泛型参数使用FrameworkElement,因为大部分的控件都是继承自这个对象,我们方便为其统一添加效果,在集成这个基类后我们需要重写基类的OnAttached和OnDetaching方法,这个里面AssociatedObject就是我们具体添加Effect的元素,在我们的示例中这个分别是TextBlock和Button对象。
2 在具体的控件中添加此效果
<Window x:Class="WpfBehavior.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:WpfBehavior" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="测试文本" Margin="2" Height="30"> <i:Interaction.Behaviors> <local:EffectBehavior></local:EffectBehavior> </i:Interaction.Behaviors> </TextBlock> <Button Content="测试" Width="80" Height="30" Margin="2"> <i:Interaction.Behaviors> <local:EffectBehavior></local:EffectBehavior> </i:Interaction.Behaviors> </Button> </StackPanel> </Grid></Window>以上就是c# WPF中System.Windows.Interactivity的使用的详细内容,更多关于WPF中System.Windows.Interactivity的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
C#中timer类的用法关于C#中timer类在C#里关于定时器类就有3个1.定义在System.Windows.Forms里2.定义在System.Threa
在C#的Windows应用程序中打开网址需使用System.Diagnostics命名空间中的Process类,下面是源代码:System.Diagnostic
本文实例讲述了C#及WPF获取本机所有字体和颜色的方法。分享给大家供大家参考。具体如下:WPF获取所有的字体:System.Drawing.Text.Insta
本文实例讲述了C#中WPF使用多线程调用窗体组件的方法。分享给大家供大家参考。具体如下:Threadthread=newThread(newThreadStar
用c#中创建一个windows服务非常简单,与windows服务相关的类都在System.ServiceProcess命名空间下。每个服务都需要继承自Servi