据此篇文章,我们继续来谈谈Caliburn.Mirco的Action参数传递机制。因此程序结构都是默认MVVM的形式。
基本机制
它的机制是——
Caliburn.Micro 的智能对象参数绑定机制通过约定和反射使得视图和视图模型之间的交互变得更加直观和简洁。通过
cal:Message.Attach
语法(附加属性的方法,其中cal是我们引入caliburn.mirco的命名空间的别名),你可以在 XAML 中定义事件处理,并且 Caliburn.Micro 会自动将参数传递给视图模型中的方法。
那具体内部怎么实现的,我们这里不深究,而是去看怎么使用这个机制。但是其基本机制如下,个人总结,仅供参考。
命名约定:Caliburn.Micro 使用命名约定来匹配 XAML 中的事件处理和视图模型中的方法。
参数自动绑定:当事件被触发时,Caliburn.Micro 可以自动将事件参数传递给对应的视图模型方法。例如,按钮的
Click
事件可以将RoutedEventArgs
传递给视图模型方法。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后,我们看看效果。
但是使用之前来了解其约定和机制:
控件命名约定:
- 在视图中,控件命名应该遵循一定的约定。例如,一个按钮的名称可以包含事件名称和方法名称的组合。
视图模型方法命名:
- 在视图模型中,方法的命名应该与控件的名称相对应。
其基本机制是
-
命名约定:Caliburn.Micro 使用命名约定来匹配 XAML 中的事件处理和视图模型中的方法。例如,按钮的
Click
事件可以自动映射到视图模型中的ButtonName_Click
方法。 -
参数自动绑定:当事件被触发时,Caliburn.Micro 可以自动将事件参数传递给对应的视图模型方法。例如,按钮的
Click
事件可以将RoutedEventArgs
传递给视图模型方法。 -
Action 语法:使用
cal:Message.Attach
语法来明确指定事件和对应的视图模型方法。
它的原理是——
Caliburn.Micro 使用反射和约定来绑定视图中的控件事件和视图模型中的方法。以下是这个过程的基本原理:
查找控件:
- Caliburn.Micro 在视图中查找所有控件,并读取它们的
Name
属性。解析事件和方法:
- 根据控件的
Name
属性,Caliburn.Micro 解析出控件类型(如Button
)和事件名称(如Click
)。查找方法:
- 在视图模型中查找与事件名称对应的方法。在这个示例中,Caliburn.Micro 查找一个名为
ButtonClick
的方法。绑定事件:
- 使用反射将控件的事件(如按钮的
Click
事件)绑定到视图模型中的方法。触发方法:
- 当控件的事件被触发时,Caliburn.Micro 调用视图模型中的相应方法。
所以当引入了这个类库之后,我们有如下方便的操作。
1)直接写一个空间Name让它自动去mvvm中匹配对应的方法名
在视图层
<Button Content="Button" Name="ButtonTest"/>
在MVVM中
public void ButtonTest()
{
Value++;//视图中的某个参数
}
那么他会去匹配到ButtonTest这个方法。我们断点调试就可以看到它直接到这里。是不是很爽。
传参机制
2)当我们想要传入参数时,可以怎么做?它具备怎样的规则?
参数匹配规则
- 事件参数:如果方法有一个参数,Caliburn.Micro 会尝试将事件参数(如
RoutedEventArgs
)传递给方法。- 属性名匹配:如果方法有多个参数,Caliburn.Micro 会尝试通过反射来匹配方法参数的名称和类型。
- 默认值和类型匹配:如果找不到确切匹配的参数,框架会尝试使用默认值或进行类型转换,以满足方法签名。
一)使用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)]"/>
其中
-
cm:Message.Attach是 Caliburn.Micro 提供的附加属性,用于将视图中的事件绑定到视图模型中的方法。
[Event Click]
指定了按钮的 Click 事件。[Action ButtonClick(1,2,tb.Text)]
指定了视图模型中的ButtonClick
方法,并传递Click
事件的参数。
此时可以看到,我们可以很好滴直接传入view中的某个控件的属性作为参数。但是当我们不明确指出它的参数的时候,是否可以?这就有另外一个机制,就是占位符。
三)使用占位符的形式传参
我总结如下
$eventArgs:这是一个占位符,表示事件参数。Caliburn.Micro 会自动将
Click
事件的RoutedEventArgs
传递给ButtonClick
方法。$dataContext
:这是一个特殊的占位符,表示按钮所在的上下文(DataContext
)。在 MVVM 模式中,DataContext
通常是绑定到视图的视图模型。[Event Click] = [Action EventAction($dataContext)]
:这段语法表示当按钮的Click
事件触发时,调用视图模型中的EventAction
方法,并将DataContext
作为参数传递给该方法。在这个示例中,当你点击按钮时,EventAction
方法会被调用,并且dataContext
参数会被传递给它。在EventAction
方法中,dataContext
参数就是视图模型的实例本身(MainViewModel
)$view
:在这里,$view
占位符表示触发事件的视图元素本身。在这个例子中,视图元素是按钮。$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,我们就可以很清楚的知道,当前它传入的参数是什么。可以很清楚的知道参数类型。
这几个方法的使用心得——》
标签:模型,视图,Micro,事件,Action,Caliburn,方法 From: https://blog.csdn.net/weixin_42031602/article/details/139339748
$dataContext
:用于将数据上下文(通常是视图模型实例)作为参数传递给方法。$eventArgs
:用于将事件参数作为参数传递给方法。$view
:用于将触发事件的视图元素本身作为参数传递给方法。选择使用
$dataContext
、$eventArgs
或$view
取决于你需要在事件处理方法中处理的数据。如果你需要访问视图模型实例,使用$dataContext
;如果你需要处理事件参数,使用$eventArgs
;如果你需要访问触发事件的视图元素,使用$view
使用
$this
:
- 可以将当前视图的实例传递给视图模型方法。
- 方便在视图模型中直接访问当前视图的属性和方法。
- 适用于需要在视图模型中直接操作视图的情况。
但需要注意,使用
$this
会引入视图模型对视图的直接依赖,可能会破坏 MVVM 架构的一些原则,因此应该谨慎使用。