Composite Commands

在许多情况下,视图模型定义的命令将绑定到关联视图中的控件,以便用户可以直接从视图中调用该命令。但是,在某些情况下,您可能希望能够从应用程序UI的父视图中的控件调用一个或多个视图模型上的命令。

例如,如果您的应用程序允许用户同时编辑多个项目,您可能希望允许用户使用应用程序工具栏或功能区中的按钮所代表的单个命令来保存所有项目。在这种情况下,Save All命令将调用每个项目的视图模型实例实现的每个Save命令,如下图所示。

Prism通过CompositeCommand课程支持这种情况。

CompositeCommand类表示从多个子指令构成的指令。调用复合命令时,将依次调用其每个子命令。在需要在UI中将一组命令表示为单个命令或者要调用多个命令来实现逻辑命令的情况下,它非常有用。

CompositeCommand类维护子类命令列表 (DelegateCommand实例)。CompositeCommand类的Execute方法依次调用每个子类的Execute命令方法。CanExecute方法类似地调用每个子命令的CanExecute方法,但是如果无法执行任何子命令,则该CanExecute方法将返回false。换句话说,默认情况下,CompositeCommand只有在可以执行所有子命令时才能执行。

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

创建Composite Commands

要创建复合命令,请实例化一个CompositeCommand实例,然后将其公开为ICommandComponsiteCommand属性。

public class ApplicationCommands
{
private CompositeCommand _saveCommand = new CompositeCommand();
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
}

使得Composite Commands全局可用

通常,CompositeCommands在整个应用程序中共享,需要全局可用。当您CompositeCommand在整个应用程序中使用同一个CompositeCommand实例注册子命令时,这一点很重要。这需要在应用程序中将CompositeCommand作为单例取消。这可以通过使用依赖注入(DI)或将CompositeCommand定义为静态类来完成。

使用依赖注入

定义CompositeCommands的第一步是创建一个接口。

public interface IApplicationCommands
{
CompositeCommand SaveCommand { get; }
}

接下来,创建一个实现该接口的类。

public class ApplicationCommands : IApplicationCommands
{
private CompositeCommand _saveCommand = new CompositeCommand();
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
}

定义ApplicationCommands类后,必须将其注册为容器的单例。

public partial class App : PrismApplication
{
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IApplicationCommands, ApplicationCommands>();
}
}

接下来,请求IApplicationCommandsViewModel构造函数中的接口。一旦有了ApplicationCommands该类的实例,现在可以使用适当的CompositeCommand注册DelegateCommands。

public DelegateCommand UpdateCommand { get; private set; }

public TabViewModel(IApplicationCommands applicationCommands)
{
UpdateCommand = new DelegateCommand(Update);
applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}

使用静态类

创建一个代表CompositeCommands的静态类

public static class ApplicationCommands
{
public static CompositeCommand SaveCommand = new CompositeCommand();
}

在ViewModel中,将子命令与静态ApplicationCommands类关联。

    public DelegateCommand UpdateCommand { get; private set; }

    public TabViewModel()
{
UpdateCommand = new DelegateCommand(Update);
ApplicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
}

注意

为了提高代码的可维护性和可测试性,建议您使用可靠性注入方法。

绑定全局可用命令

一旦创建了CompositeCommands,就必须将它们绑定到UI元素以调用命令。

使用依赖注入 (Dependency Injection)

使用DI时,必须将IApplicationCommands暴露给View。在视图的ViewModel中,请IApplicationCommands在构造函数中请求并IApplicationCommands为该实例设置type属性。

public class MainWindowViewModel : BindableBase
{
private IApplicationCommands _applicationCommands;
public IApplicationCommands ApplicationCommands
{
get { return _applicationCommands; }
set { SetProperty(ref _applicationCommands, value); }
} public MainWindowViewModel(IApplicationCommands applicationCommands)
{
ApplicationCommands = applicationCommands;
}
}

在视图中,将按钮绑定到ApplicationCommands.SaveCommand属性。这SaveCommand是在ApplicationCommands类上定义的属性。

<Button Content="Save" Command="{Binding ApplicationCommands.SaveCommand}"/>

使用静态类

如果您使用的是静态类方法,则以下代码示例演示如何将按钮绑定到WPF中的静态ApplicationCommands类。

<Button Content="Save" Command="{x:Static local:ApplicationCommands.SaveCommand}" />

取消注册命令

如前面的示例所示,使用该CompositeCommand.RegisterCommand方法注册子命令。但是,当您不再希望响应CompositeCommand或者您要销毁View / ViewModel以进行垃圾回收时,您应该使用该CompositeCommand.UnregisterCommand方法取消注册子命令。

public void Destroy()
{
_applicationCommands.UnregisterCommand(UpdateCommand);
}
重要

您必须从CompositeCommand不再需要View / ViewModel(为GC准备好)时取消注册您的命令。否则你会引入内存泄漏。

在活动视图上执行命令

父视图级别的复合命令通常用于协调如何调用子视图级别的命令。在某些情况下,您将需要执行所有显示视图的命令,如前面所述的Save All命令示例中所示。在其他情况下,您将希望仅在活动视图上执行该命令。在这种情况下,复合命令将仅对被视为活动的视图执行子命令; 它不会在非活动的视图上执行子命令。例如,您可能希望在应用程序的工具栏上实现缩放命令,该命令仅导致当前活动项目被缩放,如下图所示。

为了支持这种情况,Prism提供了IActiveAware界面。该IActiveAware接口定义了一个IsActive返回属性true时实施者是活动的,并且IsActiveChanged当活动状态改变时引发事件。

您可以IActiveAware在视图或ViewModel上实现该接口。它主要用于跟踪视图的活动状态。视图是否处于活动状态由特定控件内的视图决定。例如,对于Tab控件,有一个适配器将当前选定选项卡中的视图设置为活动状态。

DelegateCommand类还实现了IActiveAware接口。CompositeCommand可被配置成评估子类DelegateCommands的活动状态(除了CanExecute通过指定状态)truemonitorCommandActivity在构造参数。当此参数设置为时trueCompositeCommand类在确定方法的返回值以及在CanExecute方法中执行子命令时将考虑每个子DelegateCommand的活动状态Execute

    public class ApplicationCommands : IApplicationCommands
{
private CompositeCommand _saveCommand = new CompositeCommand(true);
public CompositeCommand SaveCommand
{
get { return _saveCommand; }
}
}

monitorCommandActivity参数为时trueCompositeCommand该类表现出以下行为:

  • CanExecutetrue仅在可以执行所有活动命令时返回。根本不会考虑不活动的子命令。
  • Execute:执行所有活动命令。根本不会考虑不活动的子命令。

通过IActiveAware在ViewModel上实现界面,当您的视图变为活动或非活动时,您将收到通知。当视图的活动状态更改时,您可以更新子命令的活动状态。然后,当用户调用复合命令时,将调用活动子视图上的命令。

public class TabViewModel : BindableBase, IActiveAware
{
private bool _isActive;
public bool IsActive
{
get { return _isActive; }
set
{
_isActive = value;
OnIsActiveChanged();
}
} public event EventHandler IsActiveChanged; public DelegateCommand UpdateCommand { get; private set; } public TabViewModel(IApplicationCommands applicationCommands)
{
UpdateCommand = new DelegateCommand(Update);
applicationCommands.SaveCommand.RegisterCommand(UpdateCommand);
} private void Update()
{
//implement logic
} private void OnIsActiveChanged()
{
UpdateCommand.IsActive = IsActive; //set the command as active
IsActiveChanged?.Invoke(this, new EventArgs()); //invoke the event for al listeners
}
}

Prism_Composite Commands(3)的更多相关文章

  1. useful commands for Kubernetes beginners

    Get pod ip and their coordinating NODE $ kubectl get pods -o wide If you want to get detailed inform ...

  2. useful commands for docker beginner

    You may want to add my wechat public account or add my technical blog's RSS feed This list is meant ...

  3. useful Ansible commands

    This article includes some useful Ansible commands. I will try to write blogs by English. You may wa ...

  4. The common Linux Commands

    Linux的命令总结 1. man:在线请求系统帮助 例:man mkdir NAME:这个命令的完整全名 mk(make directories) SYNOPSIS:这个命令的基本语法 mkdir ...

  5. The commands of Disk

    The commands of Disk fdisk( the disk size is less 2TB) fdisk - partition table manipulator for Linux ...

  6. Network Basic Commands Summary

    Network Basic Commands Summary set or modify hostname a)     temporary ways hostname NEW_HOSTNAME, b ...

  7. linux commands

    abrt-cli --since ;查看abrt捕捉的异常 alias ;别名,alias rm='rm -i':使用“ \rm ” 使用原命令 alsamixer ;图形音量调节,q 增加左声道, ...

  8. OWIN 中 K Commands 与 OwinHost.exe 相等吗?

    OwinHost.exe: While some will want to write a custom process to run Katana Web applications, many wo ...

  9. OWIN 中 K Commands(OwinHost.exe)与 Microsoft.AspNet.Hosting 的角色问题

    问题详情:K Commands(OwinHost.exe)是不是 OWIN 中的 Host 角色?如果是,那 Microsoft.AspNet.Hosting 对应的是 OWIN 中的哪个角色? OW ...

随机推荐

  1. 【已解决】解决IntelliJ IDEA控制台输出中文乱码问题

    IntelliJ IDEA 真的是一款很方便的Java开发工具,但是关于中文乱码这个问题我不得不吐槽,这个编码也弄得这么麻烦干嘛,真想找idea开发者干架,我敢打包票我能在一分钟之内一拳飞过去让他跪下 ...

  2. IOS UISwitch 控件

    转自:http://my.oschina.net/wolx/blog/396680 一 UISwitch 简介 二 UISwitch 创建 三设置选中状态 四 添加监听 五 测试代码 5.1 代码 5 ...

  3. iOS开发-KVO的奥秘

    转自:http://www.jianshu.com/p/742b4b248da9 序言 在iOS开发中,苹果提供了许多机制给我们进行回调.KVO(key-value-observing)是一种十分有趣 ...

  4. DRF Django REST framework 之 路由器与版本控制组件(七)

    路由器 一些Web框架提供了用于自动确定应如何将应用程序的URL映射到处理传入请求的逻辑的功能. 而DRF的路由器组件也提供了一种简单,快速且一致的方式将视图逻辑映射到一组URL上. 路由器组件的使用 ...

  5. linux-iptables增、删、改、保存

    iptables基础: iptables的5条链分别是: prerouting 路由前 input 发到本机进程的报文 ouput 本机某进程发出的报文 forword 转发 postrouting ...

  6. Day 03 作业

    简述变量的组成 变量名,赋值符号,变量值 简述变量名的命名规范 变量名应该能反映变量值所描述的状态 变量名必须以字母数字下划线组合且不能以数字开头 变量名不能是关键字 简述注释的作用 让后面的代码失效 ...

  7. 《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看白不看,看了还想看

    1. 简介 上一篇介绍了自动化框架的架构,今天宏哥就带领小伙伴或者童鞋们开始开工往这个框架里开始添砖加瓦.主要是介绍一个框架unittest单元测试框架和一种设计思想POM. 2. unittest单 ...

  8. Cisco学习记录(一):Cisco Packet Tracer官网下载方法

    通过Cisco Packet Tracer学习计算机网络知识 本人大三狗一枚,一直以来都在学java, python, web开发的我,经过一番决定,毅然决然要开始深入学习计算机网络!通过Cisco ...

  9. CSS动态表达式

    样式:style:expression(脚本) 如: 1 _top: expression(this.offsetHeight); _top: expression(eval(document.doc ...

  10. ELK 理论小知识

    ELK 是现阶段众多企业单位都在使用的一种日志分析系统,它能够方便的为我们收集你想要的日志并且展示出来 ELK是Elasticsearch.Logstash.Kibana的简称,这三者都是开源软件,通 ...