據此篇文章,我們繼續來談談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,我們就可以很清楚的知道,當前它傳入的參數是什么。可以很清楚的知道參數類型。
這幾個方法的使用心得——》
$dataContext
:用于將數據上下文(通常是視圖模型實例)作為參數傳遞給方法。$eventArgs
:用于將事件參數作為參數傳遞給方法。$view
:用于將觸發事件的視圖元素本身作為參數傳遞給方法。選擇使用
$dataContext
、$eventArgs
或$view
取決于你需要在事件處理方法中處理的數據。如果你需要訪問視圖模型實例,使用$dataContext
;如果你需要處理事件參數,使用$eventArgs
;如果你需要訪問觸發事件的視圖元素,使用$view
使用
$this
:
- 可以將當前視圖的實例傳遞給視圖模型方法。
- 方便在視圖模型中直接訪問當前視圖的屬性和方法。
- 適用于需要在視圖模型中直接操作視圖的情況。
但需要注意,使用
$this
會引入視圖模型對視圖的直接依賴,可能會破壞 MVVM 架構的一些原則,因此應該謹慎使用。