操作
操作在不修改對象的情況下為對象添加額外的功能。例如,關(guān)閉按鈕關(guān)閉選項卡或表單,并顯示一個確認對話框,您可以在MVVM應用程序中使用操作來實現(xiàn)這一點。
- 確認操作
- 事件到命令的操作
- 鍵命令操作
- 自定義操作
確認行為
提示:
MVVM 最佳實踐演示下面的文本在DevExpressMVVM 最佳實踐演示中有一個相關(guān)示例。
Group:API 代碼示例
Module:操作
Example:簡單操作
23.1 Demo Center:啟動演示
一個簡單的確認操作只能附加到一個可取消的事件(例如,表單關(guān)閉或編輯值更改)。要實現(xiàn)自定義操作,定義一個從ConfirmationBehavior類派生的類,它包含兩個虛擬字符串屬性,用于確認消息框的標題和文本。覆蓋這些屬性來分配文本字符串,構(gòu)造函數(shù)應該繼承基類構(gòu)造函數(shù),其參數(shù)等于觸發(fā)此行為的事件的名稱。
C#:
public class FormCloseBehavior : ConfirmationBehavior<FormClosingEventArgs> { public FormCloseBehavior() : base("FormClosing") { } protected override string GetConfirmationCaption() { return "Confirm exit"; } protected override string GetConfirmationText() { return "Do you really want to exit the application?"; } }
VB.NET:
Public Class FormCloseBehavior Inherits ConfirmationBehavior(Of FormClosingEventArgs) Public Sub New() MyBase.New("FormClosing") End Sub Protected Overrides Function GetConfirmationCaption() As String Return "Confirm exit" End Function Protected Overrides Function GetConfirmationText() As String Return "Do you want to exit the application?" End Function End Class
ConfirmationBehavior類的最后一個虛擬屬性是布爾類型的Confirm屬性,您還可以覆蓋它來指定相關(guān)事件的取消條件。
C#:
//Inverted confirmation logic protected override bool Confirm() { if(MessageBox.Show(GetConfirmationText(), GetConfirmationCaption(), MessageBoxButtons.YesNo) == DialogResult.Yes) return false; else return true; }
VB.NET:
'Inverted confirmation logic Protected Overrides Function Confirm() As Boolean If MessageBox.Show(GetConfirmationText(), GetConfirmationCaption(), MessageBoxButtons.YesNo) = DialogResult.Yes Then Return False Else Return True End If End Function
使用MvvmContext組件的API將此操作附加到目標UI元素。
C#:
//View mvvmContext.AttachBehavior<FormCloseBehavior>(this);
VB.NET:
'View mvvmContext.AttachBehavior(Of FormCloseBehavior)(Me)
您可以通過將操作聲明從單獨的類移至通用類來簡化此過程。
C#:
mvvmContext1.AttachBehavior<ConfirmationBehavior<ChangingEventArgs>>(checkEdit1, behavior => { behavior.Caption = "CheckEdit State Changing"; behavior.Text = "This checkEdit's checked-state is about to be changed. Are you sure?"; behavior.Buttons = ConfirmationButtons.YesNo; behavior.ShowQuestionIcon = true; }, "EditValueChanging");
VB.NET:
mvvmContext1.AttachBehavior(Of ConfirmationBehavior(Of ChangingEventArgs))(checkEdit1, Sub(behavior) behavior.Caption = "CheckEdit State Changing" behavior.Text = "This checkEdit's checked-state is about to be changed. Are you sure?" behavior.Buttons = ConfirmationButtons.YesNo behavior.ShowQuestionIcon = True End Sub, "EditValueChanging")
還支持 Fluent API。
C#:
mvvmContext1.WithEvent<ChangingEventArgs>(checkEdit1, "EditValueChanging").Confirmation(behavior => { behavior.Caption = "CheckEdit State changing"; behavior.Text = "This checkEdit's checked-state is about to be changed. Are you sure?"; });
VB.NET:
mvvmContext1.WithEvent(Of ChangingEventArgs)(checkEdit1, "EditValueChanging").Confirmation(Sub(behavior) behavior.Caption = "CheckEdit State changing" behavior.Text = "This checkEdit's checked-state is about to be changed. Are you sure?" End Sub)
事件到命令的操作
提示:
下面的文本在DevExpress的MVVM最佳實踐演示中有一個相關(guān)的例子。
Group: API 代碼示例
Module:操作
Example:事件到命令的操作
23.1 Demo Center:啟動演示
如果確認操作需要接收CancelEventArgs類型參數(shù)的事件,則事件到命令操作適合所有剩余的事件,此操作將命令綁定到目標UI元素,當該元素觸發(fā)所需事件時,命令將執(zhí)行。這可以用于:
- 第三方UI元素沒有實現(xiàn)ISupportCommandBinding接口,因此不能使用MvvmContext組件的API (mvvmContext.BindCommand方法)進行綁定。
- 需要額外功能的DevExpress控件。例如,如果您需要 SimpleButton在MouseHover事件上執(zhí)行某些操作。
事件到命令操作的實現(xiàn)與確認操作類似:您需要定義一個派生自 DevExpress EventToCommandBehavior類的單獨類,在類構(gòu)造函數(shù)中,指定目標事件名稱以及應對此事件執(zhí)行的命令。
C#:
public class ClickToSayHello : DevExpress.Utils.MVVM.EventToCommandBehavior<ViewModel, EventArgs> { public ClickToSayHello() : base("Click", x => x.SayHello()) { } }
VB.NET:
Public Class ClickToSayHello Inherits DevExpress.Utils.MVVM.EventToCommandBehavior(Of ViewModel, EventArgs) Public Sub New() MyBase.New("Click", Function(x) x.SayHello()) End Sub End Class
將事件附加到命令操作與確認操作相同。
C#:
mvvmContext.AttachBehavior<ClickToSayHello>(thirdPartyButton);
VB.NET:
mvvmContext.AttachBehavior(Of ClickToSayHello)(thirdPartyButton)
Fluent API 允許您實現(xiàn)事件到命令的操作,而無需創(chuàng)建單獨的類。
C#:
mvvmContext.WithEvent<ViewModel, EventArgs>(thirdPartyButton, "Click").EventToCommand(x => x.SayHello());
VB.NET:
mvvmContext.WithEvent(Of ViewModel, EventArgs)(thirdPartyButton, "Click").EventToCommand(Function(x) x.SayHello())
鍵到命令和鍵到命令操作
提示:
下面的文本在DevExpress的MVVM最佳實踐演示中有一個相關(guān)的例子。
Group: API 代碼示例
Module:操作
Example:按鍵到命令和按鍵到命令操作
23.1 Demo Center:啟動演示
這些行為允許您在最終用戶按下特定鍵盤鍵時執(zhí)行命令。
綁定單個鍵盤快捷鍵
下面的示例ViewModel定義了顯示基于服務(wù)的通知的“OnAKey”和“OnAltKey”命令。
C#:
public class KeyAwareViewModel { protected IMessageBoxService MessageBoxService { get { return this.GetService<IMessageBoxService>(); } } public void OnAKey() { MessageBoxService.ShowMessage("Key Command: A"); } public void OnAltAKey() { MessageBoxService.ShowMessage("Key Command: Alt+A"); } }
VB.NET:
Public Class KeyAwareViewModel Protected ReadOnly Property MessageBoxService() As IMessageBoxService Get Return Me.GetService(Of IMessageBoxService)() End Get End Property Public Sub OnAKey() MessageBoxService.ShowMessage("Key Command: A") End Sub Public Sub OnAltAKey() MessageBoxService.ShowMessage("Key Command: Alt+A") End Sub End Class
使用以下MvvmContext組件的流暢API方法將這些命令綁定到相關(guān)的鍵:
- WithKey:第一個方法參數(shù)是一個UI元素,當最終用戶按下某些鍵時,必須聚焦該元素,第二個參數(shù)是一個組合鍵。
- KeyToCommand:表示要執(zhí)行的命令。
下面的代碼分別將“OnAKey”和“OnAltKey”命令綁定到“A”和“Alt+A”鍵,只有當備忘錄編輯控件當前有焦點時,按下這兩個組合鍵才能觸發(fā)相關(guān)命令。
C#:
mvvmContext.ViewModelType = typeof(KeyAwareViewModel); // Binding the "A" key mvvmContext.OfType<KeyAwareViewModel>() .WithKey(memo, Keys.A) .KeyToCommand(x => x.OnAKey()); // Binding the "Alt+A" shortcut mvvmContext.OfType<KeyAwareViewModel>() .WithKey(memo, Keys.A | Keys.Alt) .KeyToCommand(x => x.OnAltAKey());
VB.NET:
mvvmContext.ViewModelType = GetType(KeyAwareViewModel) ' Binding the "A" key mvvmContext.OfType(Of KeyAwareViewModel)().WithKey(memo, Keys.A).KeyToCommand(Function(x) x.OnAKey()) ' Binding the "Alt+A" shortcut mvvmContext.OfType(Of KeyAwareViewModel)().WithKey(memo, Keys.A Or Keys.Alt).KeyToCommand(Function(x) x.OnAltAKey())
綁定多個鍵到同一個命令
您希望將多個鍵綁定到同一個命令并將這些鍵作為參數(shù)傳遞,請使用WithKeys和KeysToCommands方法。下面是示例KeyAwareViewModel視圖模型,包含參數(shù)化的“OnKey”和“OnKeyArgs”命令,這些命令通知用戶按下了哪些鍵。
C#:
public class KeyAwareViewModel { protected IMessageBoxService MessageBoxService { get { return this.GetService<IMessageBoxService>(); } public void OnKey(Keys keys) { MessageBoxService.ShowMessage("Key Command:" + keys.ToString()); } public void OnKeyArgs(KeyEventArgs args) { string message = string.Join(", ", "KeyValue: " + args.KeyValue.ToString(), "KeyData: " + args.KeyData.ToString(), "KeyCode: " + args.KeyCode.ToString(), "Modifiers: " + args.Modifiers.ToString()); MessageBoxService.ShowMessage("Args = {" + message + "}"); } }
VB.NET:
Public Class KeyAwareViewModel Protected ReadOnly Property MessageBoxService() As IMessageBoxService Get Return Me.GetService(Of IMessageBoxService)() End Get public void OnKey(Keys keys) MessageBoxService.ShowMessage("Key Command:" & keys.ToString()) public void OnKeyArgs(KeyEventArgs args) Dim message As String = String.Join(", ", "KeyValue: " & args.KeyValue.ToString(), "KeyData: " & args.KeyData.ToString(), "KeyCode: " & args.KeyCode.ToString(), "Modifiers: " & args.Modifiers.ToString()) MessageBoxService.ShowMessage("Args = {" & message & "}") End Property
下面的代碼將這些命令同時綁定到多個熱鍵。
C#:
mvvmContext.ViewModelType = typeof(KeyAwareViewModel); // Binding to the OnKey command mvvmContext.OfType<KeyAwareViewModel>() .WithKeys(memo, new Keys[] { Keys.A, Keys.B, Keys.C }) .KeysToCommand(x => x.OnKey(Keys.None), args => args.KeyCode); // Binding to the OnKeyArgs command mvvmContext.OfType<KeyAwareViewModel>() .WithKeys(memo, new Keys[] { Keys.Shift | Keys.A, Keys.Shift | Keys.B, Keys.Shift | Keys.C}) .KeysToCommand(x => x.OnKeyArgs((KeyEventArgs)null), args => (KeyEventArgs)args);
VB.NET:
mvvmContext.ViewModelType = GetType(KeyAwareViewModel) ' Binding to the OnKey command mvvmContext.OfType(Of KeyAwareViewModel)().WithKeys(memo, New Keys() { Keys.A, Keys.B, Keys.C }).KeysToCommand(Function(x) x.OnKey(Keys.None), Function(args) args.KeyCode) ' Binding to the OnKeyArgs command mvvmContext.OfType(Of KeyAwareViewModel)().WithKeys(memo, New Keys() { Keys.Shift Or Keys.A, Keys.Shift Or Keys.B, Keys.Shift Or Keys.C}).KeysToCommand(Function(x) x.OnKeyArgs(DirectCast(Nothing, KeyEventArgs)), Function(args) CType(args, KeyEventArgs))
自定義操作
如果沒有現(xiàn)成的DevExpress操作滿足您的需求,您可以實現(xiàn)自定義操作。例如,默認情況下, Ctrl+C鍵盤組合會復制整個GridView行,如果您只需要復制所選行單元格的值,可以附加自己的操作。
C#:
public class ControlCBehavior : EventTriggerBase<System.Windows.Forms.KeyEventArgs> { public ControlCBehavior() : base("KeyDown") { } protected override void OnEvent() { if (Args.Control && Args.KeyCode == System.Windows.Forms.Keys.C) { var cbService = this.GetService<Services.IClipboardService>(); GridView View = Source as GridView; if (View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn) != null && View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn).ToString() != String.Empty) cbService.SetText(View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn).ToString()); else XtraMessageBox.Show("The value in the selected cell is null or empty!"); Args.Handled = true; } } }
VB.NET:
Public Class ControlCBehavior Inherits EventTriggerBase(Of System.Windows.Forms.KeyEventArgs) Public Sub New() MyBase.New("KeyDown") End Sub Protected Overrides Sub OnEvent() If Args.Control AndAlso Args.KeyCode = System.Windows.Forms.Keys.C Then Dim cbService = Me.GetService(Of Services.IClipboardService)() Dim View As GridView = TryCast(Source, GridView) If View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn) IsNot Nothing AndAlso View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn).ToString() <> String.Empty Then cbService.SetText(View.GetRowCellValue(View.FocusedRowHandle, View.FocusedColumn).ToString()) Else XtraMessageBox.Show("The value in the selected cell is null or empty!") End If Args.Handled = True End If End Sub End Class
這個操作使用自定義的IClipboardService服務(wù)將文本復制到剪貼板。
C#:
public class ClipboardService : IClipboardService { public void SetText(string text) { Clipboard.SetText(text); } } public interface IClipboardService { void SetText(string text); }
VB.NET:
Public Class ClipboardService Implements IClipboardService Public Sub SetText(ByVal text As String) Implements IClipboardService.SetText Clipboard.SetText(text) End Sub End Class Public Interface IClipboardService Sub SetText(ByVal text As String) End Interface
自定義操作準備好之后,注冊服務(wù)并調(diào)用AttachBehavior方法將行為附加到網(wǎng)格視圖。
C#:
mvvmContext1.RegisterService(new Services.ClipboardService()); mvvmContext1.AttachBehavior<Behaviors.ControlCBehavior>(gridView1);
VB.NET:
mvvmContext1.RegisterService(New Services.ClipboardService()) mvvmContext1.AttachBehavior(Of Behaviors.ControlCBehavior)(gridView1)
自定義操作現(xiàn)在抑制默認的快捷方式處理程序,并且只復制選定的單元格值。