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. pom父工程dependencyManagement中的jar包在子工程中不写版本号无法引入的问题

    1.遇到的问题:  本人用的idea,然后在导入别人的项目的时候,pom文件中没有报错了,但是在maven栏目中jar包却一直报红,是因为我没写版本的原因吗?不对呀,我的父工程下已经写了springb ...

  2. 华为云MVP:来自工业制造领域的微服务与云平台实践

    [摘要] 首先,和大家先聊聊的是为什么微服务.DevOps和云计算会在各个产业大行其道;其次,再谈谈微服务架构设计有那些自己独特的设计思想,和传统的SOA有什么区别;最后,我们再一起看一看在工业领域云 ...

  3. MySQL数据库开发的36条原则

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),验证通过后,输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动&quo ...

  4. 如何对IP地址进行子网划分?

    在网络行业,子网划分是必须掌握的的基础知识点,下图是IP地址分类: 子网划分主要掌握的是划分思路,接下来我以192.168.1.72/27的IP划分做为例子: CIDR:无类域间路由. 可以看出192 ...

  5. 配置基于接口地址池的DHCP

    配置基于接口地址池的DHCP 原理概述 DHCP(动态主机配置协议),采用C/S方式工作,C向S动态请求配置信息,S自动分配配置信息. 基于接口地址池的DHCP服务器,链接这个接口网段的用户都可以从该 ...

  6. gdb调试常用方法介绍

    一.概述   GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.没有统一的界面,所有的操作都是通过命令的方式进行提供.对于习惯了图形界面方式进行调试的猿猿来说可能不是很顺手,但是如果你在 ...

  7. luogu P3152 正整数序列

    题目描述 kkk制造了一个序列,这个序列里的数全是由正整数构成的.你别认为她的数列很神奇--其实就是1, 2, -, n而已.当然,n是给定的.kkk的同学lzn认为0是一个好数字(看上去很饱满有木有 ...

  8. Exponial

    Description Everybody loves big numbers (if you do not, you might want to stop reading at this point ...

  9. intellij idea使用tomcat maven plugin

    环境 java 1.8.0_111 tomcat tomcat-8.5.11 maven 3.2.5 intellij idea 14.0.3 命令行使用 建maven工程 mvn archetype ...

  10. Kerberos+SSH安装配置使用教程

    一.背景说明 最早听说KDC和Kerberos应该是大三的<应用密码学>,当时感觉这套对称密钥分发机制比非对称密钥的PKI分发机制要好理解.但几年下来由于现实中使用SSL的场景比较比(主要 ...