Prism_Composite Commands(3)

Composite Commands

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

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

1078802-20190622150307631-2037859137.png

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

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

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

Using Composite Commands视频教程

创建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命令示例中所示。在其他情况下,您将希望仅在活动视图上执行该命令。在这种情况下,复合命令将仅对被视为活动的视图执行子命令; 它不会在非活动的视图上执行子命令。例如,您可能希望在应用程序的工具栏上实现缩放命令,该命令仅导致当前活动项目被缩放,如下图所示。

1078802-20190622150406196-4481772.png

为了支持这种情况,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
        }
    }

转载于:https://www.cnblogs.com/lovexinyi/p/11068921.html

<think>好的,用户现在问的是GDL中PrismPrism_的区别。之前他让我介绍用GDL编写吊扇的例子,现在这个问题显然和之前的代码示例有关。在之前的示例中,我用到了PRISM_命令,所以用户可能在使用过程中遇到了这两个命令,想了解它们的区别。 首先,我需要确认自己是否正确理解这两个命令的不同。根据记忆,PrismPrism_在参数和功能上有所区别,可能涉及到节点数、高度、厚度以及是否封闭等参数的不同。可能需要查阅GDL文档来确认细节,避免给出错误的信息。 用户可能是在尝试修改或扩展吊扇模型时遇到了问题,例如在创建更复杂的叶片形状时,不知道应该使用哪个命令更合适。或者在使用Prism时遇到了语法错误,导致模型无法正确生成,因此想了解两者的区别以便修正代码。 另外,用户可能对GDL的版本变化不太清楚,Prism_可能是新版本中引入的命令,而Prism是旧命令,存在一些局限性。需要说明两者的兼容性和使用场景,帮助用户根据具体情况选择。 需要检查PrismPrism_的参数结构。比如,Prism的基本语法可能包括节点数、高度、节点坐标等,而Prism_可能增加了更多的参数,如厚度、是否闭合等,提供更多的灵活性。例如,在吊扇的叶片代码中,PRISM_被用来指定4个节点和厚度,这可能是因为Prism_允许直接定义厚度,而Prism需要其他方式来实现。 还要考虑用户的实际应用场景。用户可能希望创建更复杂的几何形状,或者需要参数化的控制,Prism_可能更适合,因为它提供了更多的参数选项。例如,在吊扇例子中,使用PRISM_可以方便地定义叶片的截面形状和厚度,而用Prism可能需要额外的步骤。 另外,要注意到用户可能对GDL的某些语法细节不熟悉,比如下划线的含义,是否需要特定版本的Archicad支持,或者是否有其他相关命令变体。需要明确说明这些细节,避免用户在使用时遇到兼容性问题。 总结来说,用户需要明确PrismPrism_在功能上的区别,以便正确选择和使用。需要从参数数量、功能扩展、版本兼容性等方面进行解释,并结合之前的吊扇例子中的PRISM_使用情况,具体说明为何在该案例中使用Prism_而不是Prism,以及两者的适用场景。</think>在GDL(Graphisoft Development Language)中,`PRISM` 和 `PRISM_` 是用于创建棱柱体(三维拉伸几何体)的核心命令,但二者在参数定义和功能扩展上有显著差异: --- ### **1. `PRISM` 基础命令** - **语法**: ```gdl PRISM n, h, x1, y1, x2, y2, ..., xn, yn ``` - **参数说明**: - `n`:棱柱截面的节点数量(必须 ≥3)。 - `h`:棱柱的高度(沿Z轴拉伸的长度)。 - `x1, y1, ..., xn, yn`:截面各节点的二维坐标(按顺序定义闭合多边形)。 - **特点**: - **固定参数**:必须严格按顺序定义所有节点坐标。 - **闭合性**:自动闭合首尾节点,形成封闭截面。 - **功能局限**:无法直接定义厚度或复杂属性。 - **示例**(创建一个方形立柱): ```gdl PRISM 4, 3.0, 0,0, 0,1, 1,1, 1,0 ! 4节点,高度3m,截面1x1m方形 ``` --- ### **2. `PRISM_` 扩展命令** - **语法**: ```gdl PRISM_ n, h, thickness, x1, y1, status1, x2, y2, status2, ..., xn, yn, statusn ``` - **新增参数**: - `thickness`:棱柱的壁厚(用于生成空心或带有厚度的结构)。 - `status1~n`:每个节点的状态码(控制节点类型,如光滑过渡、锐角等)。 - **扩展功能**: - **厚度控制**:通过`thickness`直接生成空心或带厚度的棱柱。 - **节点精细化**:通过`status`参数定义节点连接方式(如`15`=光滑曲线,`1`=锐角)。 - **非闭合支持**:允许开放截面(需手动控制闭合逻辑)。 - **示例**(创建带圆角的空心叶片): ```gdl PRISM_ 4, 0.02, 0.01, ! 厚度0.01m 0,0,15, ! 节点1,状态15(光滑曲线) 0.1,0,15, ! 节点2 0.8,0,15, ! 节点3 0.7,0,15 ! 节点4 ``` --- ### **关键区别总结** | 特性 | `PRISM` | `PRISM_` | |--|------------------------------| | **厚度控制** | 不支持 | 通过`thickness`参数直接定义 | | **节点状态** | 无状态码 | 可定义光滑/锐角等节点类型 | | **开放截面** | 必须闭合 | 支持开放(需手动闭合) | | **参数复杂度** | 简单 | 更高灵活性 | | **典型应用场景** | 基础拉伸体(如立柱、梁) | 复杂轮廓(叶片、装饰线条等) | --- ### **使用建议** 1. **简单几何体**:优先使用`PRISM`,代码更简洁。 2. **复杂截面**:需控制厚度、圆角或开放路径时,必用`PRISM_`。 3. **向下兼容性**:`PRISM_`在较新GDL版本中支持,旧版本可能需替代方案。 实际应用中,吊扇叶片(如您之前的示例)因需定义厚度和曲线边缘,更适合使用`PRISM_`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值