WPF在ViewModel中处理View中的事件

序言

WPF VM中处理V的事件,这是一个老生常谈的问题。
无论什么时候总能在网上搜到一些MVVM的理想主义者,企图用"你程序设计不合理“去逃避这个问题。但是现实是这个问题确实存在,我们有时候也确实需要去解决。
这里我不想依次陈列出各种方案,因为这是9102年的文章,相信读者也都能搜到各种历史资料。
最佳实践就是微软官方的Behavior的方式。这里主要结合历史资料讲一下使用方法(老瓶装新酒…)。

正文

首先是引用库,老文章可能会让使用Blend SDK,但是微软已开源了XamlBehaviorsWpf项目,并提供了官方NuGet包。
这里直接搜索 Microsoft.Xaml.Behaviors 选择对应的包即可,这里我们使用 Microsoft.Xaml.Behaviors.Wpf
在ViewModel中处理事件我们可以通过 CallMethodActionInvokeCommandAction 两种方式来解决

View的xaml里面

<Window x:Class="TestBehavior.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:b="http://schemas.microsoft.com/xaml/behaviors"
        Title="MainWindow"
        Width="100"
        Height="100"
        mc:Ignorable="d">
    <Grid>
        <Rectangle x:Name="Element"
                   Width="50"
                   Height="50"
                   Fill="Red">
            <b:Interaction.Triggers>
                <b:EventTrigger EventName="MouseLeftButtonDown">
                    <b:CallMethodAction TargetObject="{Binding}" MethodName="NoParameMethod" />
                </b:EventTrigger>
                <b:EventTrigger EventName="MouseLeftButtonDown">
                    <b:CallMethodAction TargetObject="{Binding}" MethodName="OriginParameMethod" />
                </b:EventTrigger>
                <b:EventTrigger EventName="MouseLeftButtonDown">
                    <b:InvokeCommandAction Command="{Binding NoParameCommand}" />
                </b:EventTrigger>
                <b:EventTrigger EventName="MouseLeftButtonDown">
                    <b:InvokeCommandAction Command="{Binding OneParameCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}" />
                </b:EventTrigger>
            </b:Interaction.Triggers>
        </Rectangle>
    </Grid>
</Window>

ViewModel的cs文件里面

        /// <summary>
        /// 由事件触发无参数的方法
        /// </summary>
        public void NoParameMethod()
        {
            Trace.TraceInformation(nameof(NoParameMethod));
        }

        /// <summary>
        /// 由事件触发和事件一致参数的方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OriginParameMethod(object sender, MouseButtonEventArgs e)
        {
            Trace.TraceInformation($"{nameof(OriginParameMethod)} {sender.GetType()}  {e.GetPosition(sender as IInputElement)} ");
        }

        /// <summary>
        /// 由事件触发无参数的命令
        /// </summary>
        public ICommand NoParameCommand
        {
            get
            {
                return new ActionCommand(() =>
                {
                    Trace.TraceInformation(nameof(NoParameCommand));
                });
            }
        }

        /// <summary>
        /// 由事件触发有一个参数的命令
        /// </summary>
        public ICommand OneParameCommand
        {
            get
            {
                return new ActionCommand(_ =>
                {
                    Trace.TraceInformation($"{nameof(OneParameCommand)} {_.GetType()}");
                });
            }
        }

调试输出

TestBehavior.exe Information: 0 : NoParameMethod
TestBehavior.exe Information: 0 : OriginParameMethod System.Windows.Shapes.Rectangle  30,33.5 
TestBehavior.exe Information: 0 : NoParameCommand
TestBehavior.exe Information: 0 : OneParameCommand System.Windows.Controls.Grid

拓展

某些应用场景,可能需要多个事件联合处理,比如复杂的画图板功能,地图软件的标注功能等,需要对鼠标点击并拖动,鼠标按住左键并拖动等组合操作实现不同的功能
可以继承并自定义Behavior,在Behavior中能和获取View,并注册各种事件,实现多个事件的联合处理。

如果说我看得比别人更远些,那是因为我站在巨人的肩膀上。 --牛顿

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值