Caliburn.Micro框架学习笔记——Action的参数传递机制

据此篇文章,我们继续来谈谈Caliburn.Mirco的Action参数传递机制。因此程序结构都是默认MVVM的形式。

基本机制

它的机制是——

Caliburn.Micro 的智能对象参数绑定机制通过约定和反射使得视图和视图模型之间的交互变得更加直观和简洁。通过 cal:Message.Attach 语法(附加属性的方法,其中cal是我们引入caliburn.mirco的命名空间的别名),你可以在 XAML 中定义事件处理,并且 Caliburn.Micro 会自动将参数传递给视图模型中的方法。

 那具体内部怎么实现的,我们这里不深究,而是去看怎么使用这个机制。但是其基本机制如下,个人总结,仅供参考。

  1. 命名约定:Caliburn.Micro 使用命名约定来匹配 XAML 中的事件处理和视图模型中的方法。

  2. 参数自动绑定:当事件被触发时,Caliburn.Micro 可以自动将事件参数传递给对应的视图模型方法。例如,按钮的 Click 事件可以将 RoutedEventArgs 传递给视图模型方法。

  3. Action 语法:使用 cal:Message.Attach 语法来明确指定事件和对应的视图模型方法。

 也就是说当我们想要触发事件并传入相应的参数时,在程序结构满足MVVM的情况下,我们有如下几种方法——

基本使用方法和步骤

在享受caliburn.micro给我们带来的便利之前,先来看看如果不使用它的机制的话,我们一般是怎么做的。

需要手动绑定控件的事件到代码后置文件中的事件处理程序,然后通过事件的形式的话,在后台cs代码中进行相应的逻辑书写。假设在视图层有以下代码

<Grid><Button Name="MyButton" Content="Click Me" Width="100" Height="50" Click="MyButton_Click"/>
</Grid>

 在这里,这个button绑定了一个click事件,其事件名称为MyButton_Click。然后后台代码为——

private void MyButton_Click(object sender, RoutedEventArgs e)
{MessageBox.Show("Button clicked!");
}

那如果是使用MVVM的架构的话,这里一般是使用命令的形式来进行事件触发。因此视图层需要修改为,1,引入ViewModel,2,增加命令

<Window.DataContext><local:MainViewModel />
</Window.DataContext>
<Grid><Button Content="Click Me" Width="100" Height="50" Command="{Binding MyCommand}"/>
</Grid>

 然后相对应的ViewModel代码为

 public class MainViewModel{public ICommand MyCommand { get; }//命令public MainViewModel(){MyCommand = new RelayCommand(ExecuteMyCommand);//利用RelayCommand进行命令绑定}private void ExecuteMyCommand(object parameter)//命令的要执行的逻辑{MessageBox.Show("Button clicked!");}}public class RelayCommand : ICommand//这个命令继承自ICommand,并实现{private readonly Action<object> _execute;private readonly Func<object, bool> _canExecute;public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null){_execute = execute;_canExecute = canExecute;}public event EventHandler CanExecuteChanged{add => CommandManager.RequerySuggested += value;remove => CommandManager.RequerySuggested -= value;}public bool CanExecute(object parameter)//命令执行判断{return _canExecute == null || _canExecute(parameter);}public void Execute(object parameter)//带参数传递到命令要去执行{_execute(parameter);}}

 天啊,感觉看到以上内容,感觉头大。于是当引入caliburn.Micro后,我们看看效果。

但是使用之前来了解其约定和机制:

  1. 控件命名约定

    • 在视图中,控件命名应该遵循一定的约定。例如,一个按钮的名称可以包含事件名称和方法名称的组合。
  2. 视图模型方法命名

    • 在视图模型中,方法的命名应该与控件的名称相对应。

其基本机制是

  1. 命名约定:Caliburn.Micro 使用命名约定来匹配 XAML 中的事件处理和视图模型中的方法。例如,按钮的 Click 事件可以自动映射到视图模型中的 ButtonName_Click 方法。

  2. 参数自动绑定:当事件被触发时,Caliburn.Micro 可以自动将事件参数传递给对应的视图模型方法。例如,按钮的 Click 事件可以将 RoutedEventArgs 传递给视图模型方法。

  3. Action 语法:使用 cal:Message.Attach 语法来明确指定事件和对应的视图模型方法。

 它的原理是——

Caliburn.Micro 使用反射和约定来绑定视图中的控件事件和视图模型中的方法。以下是这个过程的基本原理:

  1. 查找控件

    • Caliburn.Micro 在视图中查找所有控件,并读取它们的 Name 属性。
  2. 解析事件和方法

    • 根据控件的 Name 属性,Caliburn.Micro 解析出控件类型(如 Button)和事件名称(如 Click)。
  3. 查找方法

    • 在视图模型中查找与事件名称对应的方法。在这个示例中,Caliburn.Micro 查找一个名为 ButtonClick 的方法。
  4. 绑定事件

    • 使用反射将控件的事件(如按钮的 Click 事件)绑定到视图模型中的方法。
  5. 触发方法

    • 当控件的事件被触发时,Caliburn.Micro 调用视图模型中的相应方法。

 所以当引入了这个类库之后,我们有如下方便的操作。

1)直接写一个空间Name让它自动去mvvm中匹配对应的方法名

在视图层

<Button Content="Button" Name="ButtonTest"/>

在MVVM中

  public void ButtonTest(){Value++;//视图中的某个参数}

那么他会去匹配到ButtonTest这个方法。我们断点调试就可以看到它直接到这里。是不是很爽。

传参机制

2)当我们想要传入参数时,可以怎么做?它具备怎样的规则?

参数匹配规则

  1. 事件参数:如果方法有一个参数,Caliburn.Micro 会尝试将事件参数(如 RoutedEventArgs)传递给方法。
  2. 属性名匹配:如果方法有多个参数,Caliburn.Micro 会尝试通过反射来匹配方法参数的名称和类型。
  3. 默认值和类型匹配:如果找不到确切匹配的参数,框架会尝试使用默认值或进行类型转换,以满足方法签名。

一)使用Caliburn.micro的ActionMessage

 <Button Content="测试"><i:Interaction.Triggers><!--使用的是xmlns:i="http://schemas.microsoft.com/xaml/behaviors"中关于行为触发的机制,需要触发的是Click事件--><i:EventTrigger EventName="Click"><cm:ActionMessage MethodName="EventAction"><!--告知这个click事件一旦点击就会触发,且对应的是ViewModel中的方法EventAction--><cm:Parameter Value="1"/><!--这里就是告知这个事件触发之后会传入的参数--><cm:Parameter Value="2"/><cm:Parameter Value="3"/></cm:ActionMessage></i:EventTrigger></i:Interaction.Triggers></Button>

那么在ViewModel中,我们可以有对应的EventAction方法

  public void EventAction(int aa, int bb, int cc){}

当点击这个按钮时,断点调试会跳到这里,那我们可以根据需要进行逻辑的书写。

同理,当我们的参数没写时,是否会自动匹配?

 <TextBox Text="12" Name="aaa"/><Button Content="智能对象参数绑定-命令" Name="AAAAction"/>

 此时,当有一个方法名字为AAAAction,它的参数会传入aaa,且此时它的传入参数命名也为aaa。

二)使用智能语法匹配

使用的是附加属性的逻辑。

  <Button Content="基本智能语法-命令"cm:Message.Attach="[Event Click] = [Action EventAction(1,2,tb.Text)]"/>

 其中

  1. cm:Message.Attach是 Caliburn.Micro 提供的附加属性,用于将视图中的事件绑定到视图模型中的方法。

    • [Event Click] 指定了按钮的 Click 事件。
    • [Action ButtonClick(1,2,tb.Text)] 指定了视图模型中的 ButtonClick 方法,并传递 Click 事件的参数。

此时可以看到,我们可以很好滴直接传入view中的某个控件的属性作为参数。但是当我们不明确指出它的参数的时候,是否可以?这就有另外一个机制,就是占位符。

三)使用占位符的形式传参

我总结如下

  1. $eventArgs:这是一个占位符,表示事件参数。Caliburn.Micro 会自动将 Click 事件的 RoutedEventArgs 传递给 ButtonClick 方法。

  2. $dataContext:这是一个特殊的占位符,表示按钮所在的上下文(DataContext)。在 MVVM 模式中,DataContext 通常是绑定到视图的视图模型。[Event Click] = [Action EventAction($dataContext)]:这段语法表示当按钮的 Click 事件触发时,调用视图模型中的 EventAction 方法,并将 DataContext 作为参数传递给该方法。在这个示例中,当你点击按钮时,EventAction 方法会被调用,并且 dataContext 参数会被传递给它。在 EventAction 方法中,dataContext 参数就是视图模型的实例本身(MainViewModel
  3. $view:在这里,$view 占位符表示触发事件的视图元素本身。在这个例子中,视图元素是按钮。
  4. $this:在这里,$this 占位符表示当前视图的实例本身。在视图模型中,参数类型应该与视图类型匹配,以便接收视图的实例

其使用分别为——

  <Button Content="$eventArgs参数-命令"cm:Message.Attach="[Event Click] = [Action EventAction($eventArgs)]"/><Button Content="$dataContext参数-命令"cm:Message.Attach="[Event Click] = [Action EventAction($dataContext)]"/><Button Content="$view参数-命令"cm:Message.Attach="[Event Click] = [Action EventAction($view)]"/><Button Content="$this参数-命令"cm:Message.Attach="[Event Click] = [Action EventAction($this)]"/>

 然后我们ViewModel层的方法有

 public void EventAction(object arg){}

此时我们可以断点到这个方法,然后去看这个arg,我们就可以很清楚的知道,当前它传入的参数是什么。可以很清楚的知道参数类型。

这几个方法的使用心得——》

  • $dataContext:用于将数据上下文(通常是视图模型实例)作为参数传递给方法。
  • $eventArgs:用于将事件参数作为参数传递给方法。
  • $view:用于将触发事件的视图元素本身作为参数传递给方法。

选择使用 $dataContext$eventArgs$view 取决于你需要在事件处理方法中处理的数据。如果你需要访问视图模型实例,使用 $dataContext;如果你需要处理事件参数,使用 $eventArgs;如果你需要访问触发事件的视图元素,使用 $view

使用 $this

  • 可以将当前视图的实例传递给视图模型方法。
  • 方便在视图模型中直接访问当前视图的属性和方法。
  • 适用于需要在视图模型中直接操作视图的情况。

但需要注意,使用 $this 会引入视图模型对视图的直接依赖,可能会破坏 MVVM 架构的一些原则,因此应该谨慎使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】探索文件读写函数的全貌

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 &#x1f525;引言 本章将介绍文件读取函数的相关知识和展示使用场景&am…

vue中如何进行Markdown文档展示与解析

vue中如何进行Markdown文档展示与解析 一、安装插件二、如何使用 需求&#xff1a;接口返回了一个政策详情页面&#xff0c;里面有图片&#xff0c;用v-html展示的是url&#xff0c;所以改用vue-markdown 一、安装插件 npm install vue-markdown --save二、如何使用 <vue-…

RabbitMQ 如何保证消息不丢失

开启消息确认机制&#xff1a; 在发布消息时&#xff0c;可以设置deliveryMode为2&#xff08;持久化&#xff09;&#xff0c;以确保消息不会因为RabbitMQ的崩溃而丢失。 使队列持久化&#xff1a; 通过设置durable为true&#xff0c;可以确保队列在RabbitMQ重启后依然存在。…

Python 实战:打造智能进销存系统

想象一下&#xff0c;在繁忙的商店里&#xff0c;每天都有数以百计的商品进进出出&#xff0c;库存在不断变化&#xff0c;销售数据涌入&#xff0c;而你却能轻松应对一切。是的&#xff0c;Python 可以帮你实现这一切。本文将教你如何使用 Python 构建一个智能的进销存系统&am…

学习记录-5.30

学习记录-5.30 同步在我的博客可以来看看 http://www.zhihuigou.top/ ### Golang为什么比别的语言跟擅长并发: 首先是因为Goroutine&#xff0c;算是go的一个最大的特色 是轻量级的线程,创建一个goroutine的开销非常小,大约几KB,且调度开销很低 并且goroutine的调度,并不…

React组件通信——兄弟组件

兄弟组件通信 方法一&#xff1a;状态提升 子组件先将数据传递到父组件&#xff0c;父组件再把数据传到另一个子组件中。 import { useState } from "react"; // 定义A组件&#xff0c;向B组件发送数据 function A({ onGetMsg }) {const name "this is A na…

fyne apptab布局

fyne apptab布局 AppTabs 容器允许用户在不同的内容面板之间切换。标签要么只是文本&#xff0c;要么是文本和一个图标。建议不要混合一些有图标的标签和一些没有图标的标签。 package mainimport ("fyne.io/fyne/v2/app""fyne.io/fyne/v2/container"//&…

PolarDB分布式架构学习笔记

PolarDB分布式是什么&#xff1f; 业务场景有哪些&#xff1f; 分布式焦点问题&#xff1f; 技术架构 CN DN介绍 CDC组件介绍 Columnar组件介绍 视频学习&#xff1a;PolarDB 实操课 第一讲&#xff1a;PolarDB分布式版架构介绍_哔哩哔哩_bilibili

都在说的跨网文件共享系统是什么?企业该怎么甄选?

跨网文件共享系统成为越来越受关注的产品焦点&#xff0c;那么跨网文件共享系统是什么呢&#xff1f;跨网文件共享是指在不同网络之间共享文件的过程&#xff0c;使得不同网络中的用户可以访问和使用共享的文件。 原则上而言&#xff0c;不同网络间的文件是无法共享的&#xff…

在SpringBoot中使用redis中的zset实现延迟任务

为什么使用zset实现延迟任务 ZSET&#xff08;有序集合&#xff09;适合实现延迟任务的原因主要有以下几点&#xff1a; 排序特性&#xff1a;ZSET根据分数&#xff08;score&#xff09;自动排序&#xff0c;这使得我们可以将任务的执行时间作为分数&#xff0c;从而能够轻松…

OAK相机如何将 YOLOv9 模型转换成 blob 格式?

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ashely。 专…

最新消息:腾讯大模型App“腾讯元宝“上线了

&#x1f9d9;‍♂️ 诸位好&#xff0c;吾乃斜杠君&#xff0c;编程界之翘楚&#xff0c;代码之大师。算法如流水&#xff0c;逻辑如棋局。 &#x1f4dc; 吾之笔记&#xff0c;内含诸般技术之秘诀。吾欲以此笔记&#xff0c;传授编程之道&#xff0c;助汝解技术难题。 &#…

Python代码:二十八、密码游戏

1、题目 牛牛和牛妹一起玩密码游戏&#xff0c;牛牛作为发送方会发送一个4位数的整数给牛妹&#xff0c;牛妹接收后将对密码进行破解。 破解方案如下&#xff1a;每位数字都要加上3再除以9的余数代替该位数字&#xff0c;然后将第1位和第3位数字交换&#xff0c;第2位和第4位…

2024年艺术鉴赏与科学教育国际会议(ICAASE 2024)

2024年艺术鉴赏与科学教育国际会议 2024 International Conference on Art Appreciation and Science Education 【1】会议简介 2024年艺术鉴赏与科学教育国际会议是一场集艺术、科学和教育于一体的国际性学术盛会。本次会议旨在推动艺术鉴赏与科学教育领域的深入交流与合作&am…

C语言(字符函数和字符串函数)1

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

python API自动化(接口测试基础与原理)

1.接口测试概念及应用 什么是接口 接口是前后端沟通的桥梁&#xff0c;是数据传输的通道&#xff0c;包括外部接口、内部接口,内部接口又包括&#xff1a;上层服务与下层服务接口&#xff0c;同级接口 外部接口&#xff1a;比如你要从 别的网站 或 服务器 上获取 资源或信息 &a…

SpringMVC框架学习笔记(四):模型数据 以及 视图和视图解析器

1 模型数据处理-数据放入 request 说明&#xff1a;开发中, 控制器/处理器中获取的数据如何放入 request 域&#xff0c;然后在前端(VUE/JSP/...)取出显 示 1.1 方式 1: 通过 HttpServletRequest 放入 request 域 &#xff08;1&#xff09;前端发送请求 <h1>添加主人…

使用dockerfile快速构建一个带ssh的docker镜像

不多说先给代码 FROM ubuntu:22.04 # 基础镜像 可替换为其他镜像 USER root RUN echo root:root |chpasswd RUN apt-get update -y \&& apt-get install -y git wget curl RUN apt-get install -y openssh-server vim && apt clean \&& rm -rf /tmp/…

在SpringBoot项目中实现切面执行链功能

1.定义切面执行链顶级接口 AspectHandler /*** 切面执行链**/ public interface AspectHandler {/*** 设置排除项* param excludes*/default void setExcludes(List<String> excludes) {}/*** 获取排除项* return*/default List<String> getExcludes() {return ne…

事务与并发控制

事务&#xff08;Transaction0&#xff09;&#xff1a;要么全做&#xff0c;要么全不做&#xff1b; 事务ACID&#xff1a;原子性Atomicity&#xff1b;一致性Consistency&#xff1b;隔离性Isolation&#xff1b;持久性Durability&#xff1b; 并发操作问题&#xff1a; 1.…