Commanding

除了提供对要在视图中显示或编辑的数据的访问之外,ViewModel还可能定义可由用户执行的一个或多个动作或操作。用户可以通过UI执行的动作或操作通常被定义为命令。命令提供了一种方便的方法来表示可以轻松绑定到UI中的控件的操作或操作。它们封装了实现操作或操作的实际代码,并有助于使其与视图中的实际可视化表示分离。

当用户与视图交互时,用户可以以多种不同的方式直观地表示和调用命令。在大多数情况下,它们是通过鼠标单击调用的,但也可以通过快捷键按下,触摸手势或任何其他输入事件来调用它们。视图中的控件是绑定到ViewModel命令的数据,以便用户可以使用控件定义的任何输入事件或手势来调用它们。视图中的UI控件与命令之间的交互可以是双向的。在这种情况下,可以在用户与UI交互时调用该命令,并且可以在启用或禁用基础命令时自动启用或禁用UI。

ViewModel可以将命令实现为命令对象(实现ICommand接口的对象)。可以以声明方式定义视图与命令的交互,而无需在视图的代码隐藏文件中使用复杂的事件处理代码。例如,某些控件固有地支持命令并提供Command可以是绑定到ICommandViewModel提供的对象的数据的属性。在其他情况下,命令行为可用于将控件与ViewModel提供的命令方法或命令对象相关联。

实现ICommand界面很简单。Prism提供了DelegateCommand这个界面的实现,您可以在应用程序中轻松使用它。

[Using Delegate Commands视频教程](Prism.assets/Prism - Using Delegate Commands.mp4)

DelegateCommand

Prism DelegateCommand类封装了两个委托,每个委托引用在ViewModel类中实现的方法。它通过调用这些委托来实现ICommand接口ExecuteCanExecute方法。您可以在DelegateCommand类构造函数中指定ViewModel方法的委托。例如,以下代码示例显示如何DelegateCommand通过指定OnSubmit和CanSubmit ViewModel方法的委托来构造表示Submit命令的实例。然后,该命令通过只读属性公开给视图,该属性返回对该参数的引用DelegateCommand

public class ArticleViewModel
{
public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand<object>(Submit, CanSubmit);
} void Submit(object parameter)
{
//implement logic
} bool CanSubmit(object parameter)
{
return true;
}
}

DelegateCommand对象上调用Execute方法时,它只是通过您在构造函数中指定的委托将调用转发到ViewModel类中的方法。同样,CanExecute调用该方法时,将调用ViewModel类中的相应方法。CanExecute构造函数中方法的委托是可选的。如果没有指定一个委托,DelegateCommand将始终返回trueCanExecute

DelegateCommand班是一个泛型类型。type参数指定传递给ExecuteCanExecute方法的命令参数的类型。在前面的示例中,command参数是type object非通用的版本DelegateCommand类也通过棱镜用于提供当没有所需的命令参数,并且被定义为如下:

public class ArticleViewModel
{
public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand(Submit, CanSubmit);
} void Submit()
{
//implement logic
} bool CanSubmit()
{
return true;
}
}

所述DelegateCommand故意阻止使用值类型(int,双,布尔等)。因为ICommand需要一个object具有值类型T将导致当意外行为CanExecute(null)XAML初始化命令绑定期间被调用。使用default(T)被认为是被拒绝作为解决方案,因为实现者无法区分有效值和默认值。如果要将值类型用作参数,则必须使用DelegateCommand<Nullable<int>>或使用简写?语法(DelegateCommand<int?>)使其可为空。

从View调用DelegateCommands

有许多方法可以将视图中的控件与ViewModel提供的命令对象相关联。某些WPF,Xamarin.Forms和UWP控件可以通过Command属性轻松地绑定到命令对象。

<Button Command="{Binding SubmitCommand}" CommandParameter="OrderId"/>

也可以使用CommandParameter属性选择性地定义命令参数。期望参数的类型在DelegateCommand<T>泛型声明中指定。当用户与该控件交互时,控件将自动调用目标命令,并且命令参数(如果提供)将作为参数传递给命令的Execute方法。在前面的示例中,按钮将SubmitCommand在单击时自动调用。此外,如果CanExecute指定了委托,则CanExecute返回时将自动禁用该按钮,如果返回false则将启用该按钮true

Raising Change Notifications

ViewModel通常需要指示命令CanExecute状态的更改,以便UI中绑定到该命令的任何控件都将更新其启用状态以反映绑定命令的可用性。在DelegateCommand提供了几种这些通知发送到用户界面。

RaiseCanExecuteChanged

RaiseCanExecuteChanged每当需要手动更新绑定的UI元素的状态时,请使用该方法。例如,当IsEnabled属性值更改时,我们调用RaiseCanExecuteChanged属性的setter来通知UI状态更改。

private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
SetProperty(ref _isEnabled, value);
SubmitCommand.RaiseCanExecuteChanged();
}
}

ObservesProperty

如果命令应在属性值更改时发送通知,则可以使用该ObservesProperty方法。使用该ObservesProperty方法时,只要提供的属性的值发生更改,DelegateCommand将自动调用RaiseCanExecuteChanged以通知UI状态更改。

public class ArticleViewModel : BindableBase
{
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set { SetProperty(ref _isEnabled, value); }
} public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled);
} void Submit()
{
//implement logic
} bool CanSubmit()
{
return IsEnabled;
}
}

注意

使用该ObservesProperty方法时,您可以链接注册多个属性以供观察。示例:ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave)

ObservesCanExecute

如果您CanExecute是简单Boolean属性的结果,则可以省去声明CanExecute委托,并使用该ObservesCanExecute方法。ObservesCanExecute当注册的属性值发生变化时,它不仅会向UI发送通知,而且还会使用与实际CanExecute委托相同的属性。

public class ArticleViewModel : BindableBase
{
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set { SetProperty(ref _isEnabled, value); }
} public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesCanExecute(() => IsEnabled);
} void Submit()
{
//implement logic
}
}
警告

不要尝试链式注册ObservesCanExecute方法。CanExcute代表只能观察到一个属性。

基于Task-Based的DelegateCommand

async/await调用Execute委托内部的异步方法是一个非常常见的要求。每个人的第一直觉是他们需要一个AsyncCommand,但这种假设是错误的。ICommand本质上是同步的,并且代表ExecuteCanExecute代表应被视为事件。这意味着这async void是一个非常有效的语法用于命令。使用异步方法有两种方法DelegateCommand

  • 方法一
public class ArticleViewModel
{
public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand(Submit);
} async void Submit()
{
await SomeAsyncMethod();
}
}
  • 方法二
public class ArticleViewModel
{
public DelegateCommand SubmitCommand { get; private set; } public ArticleViewModel()
{
SubmitCommand = new DelegateCommand(async ()=> await Submit());
} Task Submit()
{
return SomeAsyncMethod();
}
}

Prism_Commanding(2)的更多相关文章

随机推荐

  1. aspnet boilerplate 随笔二

    项目框架介绍: 1:Application: 在service里面事件具体业务,Dto相当于viewmodel实现了验证 2:Core:实现了数据层Model   3:EntityFrameworkC ...

  2. 爬虫(六):XPath、lxml模块

    1. XPath 1.1 什么是XPath XPath(XML Path Language) 是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历. 1.2 ...

  3. Oracle 创建用户,赋予指定表名/视图只读权限

    步骤指南 创建用户 格式:; 语法:create user 用户名 identified by 密码; 注:密码不行的话,前后加(单引号):' create user TEST identified ...

  4. Android 上下文菜单 ActionMode

    public class MainActivity extends Activity { private Button button; private ActionMode actionMode; @ ...

  5. webpack生成的css文件background-image url图片无法加载

    之前在使用webpack3构建基于less预处理的项目时,在对指定的元素使用background-image: url(xxx)来设置背景图片时,本地开发是ok的,但是在项目编译产出后背景图片就找不到 ...

  6. ASP.NET Core on K8S深入学习(11)K8S网络知多少

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.Kubernetes网络模型 我们都知道Kubernetes作为容器编排引 ...

  7. MongoDB(一):NoSQL简介、MongoDB简介

    1. NoSQL简介 1.1 什么是NoSQL NoSQL(NoSQL= Not Only SQL),意即“不仅仅是SQL",是一项全新的数据库理念,泛指非关系型的数据库. 1.2 为什么需 ...

  8. centos7 laravel 项目 npm install报错

    npm install 初始化项目依赖的前端资源   报错 ERR xxx .. socket,symbol link is not supported ... 如果报错了 重新npm install ...

  9. Laravel实现大型商城网站之用户注册短信发送项目实战功能开发

    确定短信运营商 我这里采用的云片,不过大家使用其它的也可以. 首先自己注册一个帐号,然后找到这个 点击开始接入,完成新手引导过程. 第二部的签名和模板必须填写,类似我下面填写的这样 值得注意的是这个模 ...

  10. vue中使用element组件时事件想要传递其他参数的问题

    在使用element的上传组件时在一下几个钩子中传递其他参数 图中是文件上传时的几个钩子,参数为文件或文件列表或者其他参数,但是现在我想在原有参数上传递其他参数.比如我想在on-success的钩子中 ...