行为在不修改对象的情况下向对象添加额外的功能。例如,close按钮关闭选项卡或表单,并额外显示确认对话框。您可以使用MVVM应用程序中的行为来实现这一点。
- 确认类行为
- Event-To-Command类行为
- Key-To-Command类行为
- 自定义行为
1. 确认类行为
一个简单的确认行为只能附加到一个可取消的事件(例如,表单关闭或编辑值更改)。要实现自定义行为,定义一个派生自 ConfirmationBehavior 类的类。它包含确认消息框的标题和文本的两个虚拟字符串属性。重写这些属性来分配文本字符串。类构造函数应该继承基类构造函数,其参数等于触发此行为的事件的名称。
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?";
}
}
提示:
ConfirmationBehavior 类的最后一个虚拟属性是布尔型的Confirm属性。您还可以覆盖它以指定相关事件的取消条件。
//手工把确认逻辑给反转了
protected override bool Confirm() {
return MessageBox.Show(GetConfirmationText(), GetConfirmationCaption(), MessageBoxButtons.YesNo) != DialogResult.Yes;
}
使用 MvvmContext 组件的API将此行为附加到目标UI元素。
//View
mvvmContext.AttachBehavior<FormCloseBehavior>(this);
//通过将行为声明从单独的类移到泛型类中,可以简化这个过程。
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");
Fluent API也支持的。
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?";
});
2. Event-To-Command类行为
如果确认行为需要接收CancelEventArgs类型参数的事件,则Event-to-command 类行为适合所有还需处理的事件。此行为将命令绑定到目标UI元素,当该元素触发所需事件时,将执行该命令。这可以用于:
没有实现ISupportCommandBinding接口的第三方UI元素,因此,不能使用MvvmContext组件的API (mvvmContext.BindCommand的方法)进行绑定。
需要拓展功能的DevExpress控件。例如,如果您需要一个SimpleButton来处理MouseHover 事件。
Event-to-command 类行为的实现类似于确认行为:你需要定义一个独立的类,它派生自DevExpress的EventToCommandBehavior类。在类构造函数中,指定目标事件名称和事件上应该执行的命令。
public class ClickToSayHello : DevExpress.Utils.MVVM.EventToCommandBehavior<ViewModel, EventArgs> {
public ClickToSayHello()
: base("Click", x => x.SayHello()) {
}
}
附加事件到命令行为与确认行为是一模一样的。
mvvmContext.AttachBehavior<ClickToSayHello>(thirdPartyButton);
使用Fluent API允许你实现Event-to-command类行为,而无需单独创建类。
mvvmContext
.WithEvent<ViewModel, EventArgs>(thirdPartyButton, "Click")
.EventToCommand(x => x.SayHello());
3. Key-To-Command和Keys-To-Command行为
运行例子
这些行为允许您在终端用户按下特定键盘键时执行命令。
3.1 绑定单个键盘快捷键
下面的例子中ViewModel 定义了“OnAKey”和“OnAltKey”命令,它显示了基于服务的通知。
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");
}
}
使用以下MvvmContext组件的Fluent API方法将这些命令绑定到相关的键:
| 方法名 | 参数说明 |
|---|---|
| WithKey | 第一个方法参数是一个UI元素,当最终用户按下特定的键时,必须对其进行聚焦。第二个参数是一个键组合 |
| KeyToCommand | 指应该执行的命令。 |
下面的代码分别将“OnAKey”和“OnAltKey”命令绑定到“A”和“Alt+A”键。只有当memo编辑控件当前有焦点时,按下这两个组合键才能触发相关命令。
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());
3.2 将多个按键绑定到同一个命令
如果希望将多个键绑定到同一个命令并将这些键作为参数传递,可以使用WithKeys和KeysToCommands方法。下面是例子中KeyAwareViewModelViewModel ,它包含参数化的“OnKey”和“OnKeyArgs”命令。这些命令通知用户按下了什么键。
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 + "}");
}
}
下面的代码将这些命令一次绑定到多个热键。
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);
4. 自定义行为
如果没有满足您需求的现成DevExpress行为,您可以实现自定义行为。例如,默认情况下,Ctrl+C键盘组合会复制整个GridView行。如果只需要复制所选行单元格的值,则可以附加自己的行为。
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;
}
}
}
下面行为使用将文本复制到剪贴板的自定义IClipboardService服务。
public class ClipboardService : IClipboardService {
public void SetText(string text) {
Clipboard.SetText(text);
}
}
public interface IClipboardService {
void SetText(string text);
}
自定义行为准备好之后,注册服务并调用AttachBehavior方法将行为附加到GridView。
mvvmContext1.RegisterService(new Services.ClipboardService());
mvvmContext1.AttachBehavior<Behaviors.ControlCBehavior>(gridView1);
自定义行为现在取消默认快捷处理程序并只复制选定的单元格值。
【DevExpress MVVM】中文翻译系列.文章目录
DevExpress.WindowsForms.v20.1.chm离线英文原版文档下载