彩票走势图

logo DevExpress WinForm中文手册

命令行


立即下载DevExpress WinForms

在标准的WinForms应用程序中,操作通常在事件处理程序中执行。例如,要在用户单击按钮时刷新数据,需要处理ButtonClick事件并检索数据源记录。

这种标准技术不适合分离层的MVVM概念,从数据源中提取数据的代码应该属于ViewModel层,而不是View层。在MVVM中,这些任务是通过封装动作的命令ViewModel对象来完成的,将UI元素绑定到此对象来实现所需的层分离:视图代码现在只有绑定代码,而所有业务逻辑都保留在ViewModel中,并且可以安全地更改。

DevExpress MVVM框架将所有public void方法视为可绑定的命令。下面的代码说明了如何声明使用Service显示消息框的命令,您可以通过以下链接在DevExpress demo Center中查看完整的演示。

C#:

//POCO ViewModel
public class ViewModelWithSimpleCommand {
//command
public void DoSomething() {
var msgBoxService = this.GetService<IMessageBoxService>();
msgBoxService.ShowMessage("Hello!");
}
}

VB.NET:

'POCO ViewModel
Public Class ViewModelWithSimpleCommand
'command
Public Sub DoSomething()
Dim msgBoxService = Me.GetService(Of IMessageBoxService)()
msgBoxService.ShowMessage("Hello!")
End Sub
End Class

注意:名称以“Command”结尾的方法将引发异常——重命名此类方法或使用Command属性修饰它们。

要将按钮链接到此命令,请使用BindCommand或WithCommand方法。

C#:

//View code
mvvmContext.ViewModelType = typeof(ViewModelWithSimpleCommand);
var fluent = mvvmContext.OfType<ViewModelWithSimpleCommand>();
fluent.BindCommand(commandButton, x => x.DoSomething);
\\or
fluent.WithCommand(x => x.DoSomething)
.Bind(commandButton1);

VB.NET:

'View code
mvvmContext.ViewModelType = GetType(ViewModelWithSimpleCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithSimpleCommand)()
fluent.BindCommand(commandButton, Sub(x) x.DoSomething)
'or
fluent.WithCommand(Sub(x) x.DoSomething)
.Bind(commandButton1)

WithCommand方法允许您同时绑定多个按钮。

运行演示:绑定到多个UI元素。

C#:

//View
var fluent = mvvmContext.OfType<ViewModelWithSimpleCommand>();
fluent.WithCommand(x => x.DoSomething)
.Bind(commandButton1)
.Bind(commandButton2);

VB.NET:

'View
Dim fluent = mvvmContext.OfType(Of ViewModelWithSimpleCommand)()
fluent.WithCommand(Sub(x) x.DoSomething)
.Bind(commandButton1)
.Bind(commandButton2)

可执行条件

要指定判断命令是否应该运行的条件,请声明一个Boolean method,该方法的名称以“Can”开头,后面跟着相关的命令名称,这些方法被称为CanExecute conditions。

C#:

//ViewModel
public class ViewModelWithConditionalCommand {
//Command
public void DoSomething() {
var msgBoxService = this.GetService<IMessageBoxService>();
msgBoxService.ShowMessage("Hello!");
}
//CanExecute condition
public bool CanDoSomething() {
return (2 + 2) == 4;
}
}

VB.NET:

'ViewModel
Public Class ViewModelWithConditionalCommand
'Command
Public Sub DoSomething()
Dim msgBoxService = Me.GetService(Of IMessageBoxService)()
msgBoxService.ShowMessage("Hello!")
End Sub
'CanExecute condition
Public Function CanDoSomething() As Boolean
Return (2 + 2) = 4
End Function
End Class

您也可以忽略CanExecute名称要求,并使用Command属性手动分配命令条件。

C#:

[Command(CanExecuteMethodName = "DoSomethingCriteria")]
public void DoSomething(int p) {
//command
}

VB.NET:

<Command(CanExecuteMethodName := "DoSomethingCriteria")>
Public Sub DoSomething(ByVal p As Integer)
'command
End Sub

如果CanExecute条件返回false,框架将改变链接到该命令的UI元素的状态(禁用、取消选中或隐藏该元素)。上面的代码示例来自以下演示:运行此演示并更改条件,使其始终返回false,“执行命令”按钮被禁用,因为它的相关命令不能再运行。

C#:

//ViewModel
public bool CanDoSomething() {
//always "false"
return (2 + 2) == 5;
}

VB.NET:

'ViewModel
Public Function CanDoSomething() As Boolean
'always "False"
Return (2 + 2) = 5
End Function

当发生以下情况时,框架会检查CanExecute条件:

  • UI命令绑定初始化。
  • 调用RaiseCanExecuteChanged方法。在下面的示例中,每次SelectedEntity属性更改时,都会重新检查CanDoSomething条件的返回值。

C#:

//Bindable Property
public virtual MyEntity SelectedEntity{ get; set; }

//OnChanged callback for the bindable property
protected void OnSelectedEntityChanged(){
this.RaiseCanExecuteChanged(x=>x.DoSomething());
}

//Command
public void DoSomething() {
//. . .
}

//CanExecute condition
public bool CanDoSomething() {
//. . .
}

VB.NET:

'Bindable Property
Public Overridable Property SelectedEntity() As MyEntity

'OnChanged callback for the bindable property
Protected Sub OnSelectedEntityChanged()
Me.RaiseCanExecuteChanged(Function(x) x.DoSomething())
End Sub

'Command
Public Sub DoSomething()
'. . .
End Sub

'CanExecute condition
Public Function CanDoSomething() As Boolean
'. . .
End Function

命令与参数

DevExpress MVVM框架接受public void方法作为参数化命令,您可以使用这个参数在View和ViewModel之间传递数据。

运行demo:Parameterized命令。

C#:

//ViewModel
public class ViewModelWithParametrizedCommand {
public void DoSomething(object p) {
var msgBoxService = this.GetService<IMessageBoxService>();
msgBoxService.ShowMessage(string.Format("The parameter is {0}.", p));
}
}

//View
mvvmContext.ViewModelType = typeof(ViewModelWithParametrizedCommand);
var fluent = mvvmContext.OfType<ViewModelWithParametrizedCommand>();
object parameter = 5;
fluent.BindCommand(commandButton, x => x.DoSomething, x => parameter);

VB.NET:

'ViewModel
Public Class ViewModelWithParametrizedCommand
Public Sub DoSomething(ByVal p As Object)
Dim msgBoxService = Me.GetService(Of IMessageBoxService)()
msgBoxService.ShowMessage(String.Format("The parameter is {0}.", p))
End Sub
End Class

'View
mvvmContext.ViewModelType = GetType(ViewModelWithParametrizedCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithParametrizedCommand)()
Dim parameter As Object = 5
fluent.BindCommand(commandButton, Sub(x) x.DoSomething(Nothing), Function(x) parameter)

还可以在CanExecute条件中添加参数。

运行demo:带CanExecute条件的参数化命令。

C#:

//ViewModel
public class ViewModelWithParametrizedConditionalCommand {
public void DoSomething(int p) {
var msgBoxService = this.GetService<IMessageBoxService>();
msgBoxService.ShowMessage(string.Format(
"The parameter is {0}.", p));
}
public bool CanDoSomething(int p) {
return (2 + 2) == p;
}
}

//View
mvvmContext.ViewModelType = typeof(ViewModelWithParametrizedConditionalCommand);
var fluent = mvvmContext.OfType<ViewModelWithParametrizedConditionalCommand>();
int parameter = 4;
fluent.BindCommand(commandButton, x => x.DoSomething, x => parameter);

VB.NET:

'ViewModel
Public Class ViewModelWithParametrizedConditionalCommand
Public Sub DoSomething(ByVal p As Integer)
Dim msgBoxService = Me.GetService(Of IMessageBoxService)()
msgBoxService.ShowMessage(String.Format("The parameter is {0}.", p))
End Sub
Public Function CanDoSomething(ByVal p As Integer) As Boolean
Return (2 + 2) = p
End Function
End Class

'View
mvvmContext.ViewModelType = GetType(ViewModelWithParametrizedConditionalCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithParametrizedConditionalCommand)()
Dim parameter As Integer = 4
fluent.BindCommand(commandButton, Sub(x) x.DoSomething(Nothing), Function(x) parameter)
多参数

使用对象或元组数据结构来传递多个参数。

C#:

class Parameters{
public int Parameter1 { get; set }
public string Parameter2 { get; set }
...
}
// ...
mvvmContext.OfType<MouseDownAwareViewModel>()
.WithEvent<MouseEventArgs>(label, "MouseDown")
.EventToCommand(x => x.ReportLocation, args => new Parameters{ Parameter1 = 1, Parameter2 = "2" });

VB.NET:

Friend Class Parameters
Public Property Parameter1() As Integer
Get
Set(ByVal value As Integer)
End Set
End Get
public String Parameter2
Get
Set(ByVal value As Integer)
End Set
End Get
...
' ...
mvvmContext.OfType(Of MouseDownAwareViewModel)().WithEvent(Of MouseEventArgs)(label, "MouseDown").EventToCommand(Function(x) x.ReportLocation, Function(args) New Parameters With {.Parameter1 = 1, .Parameter2 = "2"})

异步命令

如果需要执行延迟或连续的操作,请使用异步命令。要创建一个异步命令,声明一个System.Threading.Tasks.Task类型的公共方法(也可以使用async/await语法),将UI元素绑定到命令的代码保持不变,框架在命令运行时禁用此元素。

执行demo:Async命令。

C#:

//ViewModel
public class ViewModelWithAsyncCommand {
public async Task DoSomethingAsync() {
// do some work here
await Task.Delay(1000);
}
}

//View
mvvmContext.ViewModelType = typeof(ViewModelWithAsyncCommand);
var fluent = mvvmContext.OfType<ViewModelWithAsyncCommand>();
fluent.BindCommand(commandButton, x => x.DoSomethingAsync);

VB.NET:

'ViewModel
Public Class ViewModelWithAsyncCommand
Public Async Sub DoSomethingAsync() As Task
' do some work here
Await Task.Delay(1000)
End Sub
End Class

'View
mvvmContext.ViewModelType = GetType(ViewModelWithAsyncCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithAsyncCommand)()
fluent.BindCommand(commandButton, Sub(x) x.DoSomethingAsync(Nothing))

任务支持取消标记并允许您检查IsCancellationRequested属性,并在该属性返回true时中止任务。如果将此代码添加到async命令中,请使用BindCancelCommand方法创建一个UI元素来停止正在执行的async命令。DevExpress MVVM框架锁定了这个取消按钮,只有在运行相关的异步命令时才启用它。

执行demo: Async取消命令。

C#:

//ViewModel
public class ViewModelWithAsyncCommandAndCancellation {
public async Task DoSomethingAsynchronously() {
var dispatcher = this.GetService<IDispatcherService>();
var asyncCommand = this.GetAsyncCommand(x => x.DoSomethingAsynchronously());
for(int i = 0; i <= 100; i++) {
if(asyncCommand.IsCancellationRequested)
break;
// do some work here
await Task.Delay(25);
await UpdateProgressOnUIThread(dispatcher, i);
}
await UpdateProgressOnUIThread(dispatcher, 0);
}

public int Progress {
get;
private set;
}
//update the "Progress" property bound to the progress bar within a View
async Task UpdateProgressOnUIThread(IDispatcherService dispatcher, int progress) {
await dispatcher.BeginInvoke(() => {
Progress = progress;
this.RaisePropertyChanged(x => x.Progress);
});
}
}

//View
mvvmContext.ViewModelType = typeof(ViewModelWithAsyncCommandAndCancellation);
var fluent = mvvmContext.OfType<ViewModelWithAsyncCommandAndCancellation>();
fluent.BindCommand(commandButton, x => x.DoSomethingAsynchronously);
fluent.BindCancelCommand(cancelButton, x => x.DoSomethingAsynchronously);
fluent.SetBinding(progressBar, p => p.EditValue, x => x.Progress);

VB.NET:

'ViewModel
Public Class ViewModelWithAsyncCommandAndCancellation
Public Async Sub DoSomethingAsynchronously() As Task
Dim dispatcher = Me.GetService(Of IDispatcherService)()
Dim asyncCommand = Me.GetAsyncCommand(Sub(x) x.DoSomethingAsynchronously())
For i As Integer = 0 To 100
If asyncCommand.IsCancellationRequested Then
Exit For
End If
' do some work here
Await Task.Delay(25)
Await UpdateProgressOnUIThread(dispatcher, i)
Next i
Await UpdateProgressOnUIThread(dispatcher, 0)
End Sub

Private privateProgress As Integer
Public Property Progress() As Integer
Get
Return privateProgress
End Get
Private Set(ByVal value As Integer)
privateProgress = value
End Set
End Property
'update the "Progress" property bound to the progress bar within a View
Private Async Sub UpdateProgressOnUIThread(ByVal dispatcher As IDispatcherService, ByVal progress As Integer) As Task
Await dispatcher.BeginInvoke(Sub()
Me.Progress = progress
Me.RaisePropertyChanged(Sub(x) x.Progress)
End Sub)
End Sub
End Class

'View
mvvmContext.ViewModelType = GetType(ViewModelWithAsyncCommandAndCancellation)
Dim fluent = mvvmContext.OfType(Of ViewModelWithAsyncCommandAndCancellation)()
fluent.BindCommand(commandButton, Sub(x) x.DoSomethingAsynchronously)
fluent.BindCancelCommand(cancelButton, Sub(x) x.DoSomethingAsynchronously)
fluent.SetBinding(progressBar, Sub(p) p.EditValue, Sub(x) x.Progress)

WithCommand Fluent API方法还支持可取消的异步命令。

C#:

mvvmContext.ViewModelType = typeof(ViewModelWithAsyncCommandAndCancellation);
// Initialize the Fluent API
var fluent = mvvmContext.OfType<ViewModelWithAsyncCommandAndCancellation>();
// Binding for buttons
fluent.WithCommand(x => x.DoSomethingAsynchronously)
.Bind(commandButton)
.BindCancel(cancelButton);

VB.NET:

mvvmContext.ViewModelType = GetType(ViewModelWithAsyncCommandAndCancellation)
' Initialize the Fluent API
Dim fluent = mvvmContext.OfType(Of ViewModelWithAsyncCommandAndCancellation)()
' Binding for buttons
fluent.WithCommand(Sub(x) x.DoSomethingAsynchronously).Bind(commandButton).BindCancel(cancelButton)

命令触发器

触发器允许您执行与命令关联的其他View操作。有三种触发器类型,取决于触发触发器的条件:

  • “Before”触发器——允许您在目标命令执行之前执行操作。

C#:

mvvmContext.ViewModelType = typeof(ViewModelWithSimpleCommand);
var fluent = mvvmContext.OfType<ViewModelWithSimpleCommand>();
fluent.BindCommand(commandButton, x => x.DoSomething);
fluent.WithCommand(x => x.DoSomething)
.Before(() => XtraMessageBox.Show("The target command is about to be executed"));

VB.NET:

mvvmContext.ViewModelType = GetType(ViewModelWithSimpleCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithSimpleCommand)()
fluent.BindCommand(commandButton, Function(x) x.DoSomething)
fluent.WithCommand(Sub(x) x.DoSomething)
.Before(Function() XtraMessageBox.Show("The target command is about to be executed"))
  • " After "触发器——允许您在目标命令完成后执行操作。

C#:

mvvmContext.ViewModelType = typeof(ViewModelWithSimpleCommand);
var fluent = mvvmContext.OfType<ViewModelWithSimpleCommand>();
fluent.BindCommand(commandButton, x => x.DoSomething);
fluent.WithCommand(x => x.DoSomething)
.After(() => XtraMessageBox.Show("The target command has been executed"));

VB.NET:

mvvmContext.ViewModelType = GetType(ViewModelWithSimpleCommand)
Dim fluent = mvvmContext.OfType(Of ViewModelWithSimpleCommand)()
fluent.BindCommand(commandButton, Function(x) x.DoSomething)
fluent.WithCommand(Function(x) x.DoSomething).After(Function() XtraMessageBox.Show("The target command has been executed"))
  • “CanExecute”条件触发器——允许您在目标命令的CanExecute条件发生变化时执行操作。

C#:

var fluent = mvvmContext.OfType<ViewModelWithSimpleCommandAndCanExecute>();
fluent.BindCommand(commandButton, x => x.DoSomething);
// When the CanExecute condition changes, the message shows up
fluent.WithCommand(x => x.DoSomething)
.OnCanExecuteChanged(() => XtraMessageBox.Show("The CanExecute condition has changed"));

VB.NET:

Dim fluent = mvvmContext.OfType(Of ViewModelWithSimpleCommandAndCanExecute)()
fluent.BindCommand(commandButton, Function(x) x.DoSomething)
' When the CanExecute condition changes, the message shows up
fluent.WithCommand(Function(x) x.DoSomething)
.OnCanExecuteChanged(Function() XtraMessageBox.Show("The CanExecute condition has changed"))

注意,每个绑定到目标命令的UI元素都会执行触发器,当单击任何按钮时,下面的代码示例将显示一个消息框。

C#:

mvvmContext1.OfType<BulkEditViewModel>()
.WithCommand(vm => vm.RemoveFields())
.Bind(button1)
.Bind(button2)
.After(() => MessageBox.Show("Test"));

VB.NET:

mvvmContext1.OfType(Of BulkEditViewModel)()
.WithCommand(Function(vm) vm.RemoveFields())
.Bind(button1)
.Bind(button2)
.After(Function() MessageBox.Show("Test"))

Non-POCO命令

上面描述的POCO类命令允许您使用最直接且不会出错的语法,DevExpress MVVM框架还支持其他命令类型来确保遗留项目的无障碍迁移。

DevExpress delegate命令对象

委托命令是System.Windows.Input.ICommand接口的实现。

运行demo: Simple Commands

C#:

DelegateCommand command = new DelegateCommand(() => {
XtraMessageBox.Show("Hello!");
});
commandButton.BindCommand(command);

VB.NET:

Dim command As New DelegateCommand(Sub() XtraMessageBox.Show("Hello!"))
commandButton.BindCommand(command)

运行demo:带有CanExecute条件的命令

C#:

Func<bool> canExecute = () => (2 + 2 == 4);
DelegateCommand command = new DelegateCommand(() => {
XtraMessageBox.Show("Hello!");
}, canExecute);
commandButton.BindCommand(command);

VB.NET:

Dim canExecute As Func(Of Boolean) = Function() (2 + 2 = 4)
Dim command As New DelegateCommand(Sub() XtraMessageBox.Show("Hello!"), canExecute)
commandButton.BindCommand(command)

运行demo:带参数命令

C#:

DelegateCommand<object> command = new DelegateCommand<object>((v) => {
XtraMessageBox.Show(string.Format("The parameter is {0}.", v));
});
object parameter = 5;
commandButton.BindCommand(command, () => parameter);

VB.NET:

Dim command As New DelegateCommand(Of Object)(Sub(v) XtraMessageBox.Show(String.Format("The parameter is {0}.", v)))
Dim parameter As Object = 5
commandButton.BindCommand(command, Function() parameter)

运行demo:参数化CanExecute条件的命令

C#:

Func<int, bool> canExecute = (p) => (2 + 2 == p);
DelegateCommand<int> command = new DelegateCommand<int>((v) => {
XtraMessageBox.Show(string.Format("The parameter is {0}.", v));
}, canExecute);
int parameter = 4;
commandButton.BindCommand(command, () => parameter);

VB.NET:

Dim canExecute As Func(Of Integer, Boolean) = Function(p) (2 + 2 = p)
Dim command As New DelegateCommand(Of Integer)(Sub(v) XtraMessageBox.Show(String.Format("The parameter is {0}.", v)), canExecute)
Dim parameter As Integer = 4
commandButton.BindCommand(command, Function() parameter)
自定义命令类

这些对象是具有至少一个Execute方法的任意自定义类型的对象,如果需要您可以添加CanExecute方法和CanExecuteChanged事件。

运行demo:Simple Commands

C#:

CommandObject command = new CommandObject();
commandButton.BindCommand(command);

public class CommandObject {
public void Execute(object parameter) {
XtraMessageBox.Show("Hello!");
}
}

VB.NET:

Private command As New CommandObject()
commandButton.BindCommand(command)

Public Class CommandObject
Public Sub Execute(ByVal parameter As Object)
XtraMessageBox.Show("Hello!")
End Sub
End Class

运行demo:带参数命令

C#:

CommandObjectWithParameter command = new CommandObjectWithParameter();
int parameter = 4;
commandButton.BindCommand(command, () => parameter);

public class CommandObjectWithParameter {
public void Execute(object parameter) {
XtraMessageBox.Show(string.Format(
"The parameter is {0}.", parameter));
}
public bool CanExecute(object parameter) {
return object.Equals(2 + 2, parameter);
}
}

VB.NET:

Dim command As New CommandObjectWithParameter()
Dim parameter As Integer = 4
commandButton.BindCommand(command, Sub() parameter)

Public Class CommandObjectWithParameter
Public Sub Execute(ByVal parameter As Object)
XtraMessageBox.Show(String.Format("The parameter is {0}.", parameter))
End Sub
Public Function CanExecute(ByVal parameter As Object) As Boolean
Return Object.Equals(2 + 2, parameter)
End Function
End Class
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP