在做Web Dynpro程序开发过程中,由于UI组件都是系统框架封装好的,我们不希望该应用程序显示静态数据,而是希望其显示后端系统的数据。因此,我们需要定义可绑定UI元素且可在不同控制器传递数据的变量,针对UI组件进行的数据更改和属性更改都是通过修改Context页签中的变量来进行间接的操作,所以我们必须掌握上下文(Context)的定义、节点属性、节点映射及供应函数(Supply Function)的使用等相关知识。
一、如何定义控制器(Controller)上下文中(Context)的节点和属性?
每个Web Dynpro控制器都只有唯一一个Context层次数据存储结构,称为“上下文”。Context中保存的数据仅存在于控制器的生命周期内,当控制器实例终止运行后,Context保存的所有数据将会丢失。
通常是在开发阶段定义上下文Context的层次结构(即元数据)。也可以在运行时,利用相关类方法动态修改上下文的内容和结构本身。
如果没有特殊的声明,控制器Controller 的上下文所有运行时数据都是该组件专用的。通常通过上下文映射技术,一个控制器(视图或自定义)的上下文可以访问另一个自定义控制器的上下文中保存的信息。两个或两个以上的控制器可使用该技术访问相同的运行时数据,这是单个组件内各控制器之间共享数据的主要机制。(有一个例外,视图控制器不能共享给其他控制器上下文数据,因为违反了MVC设计原则)。
Context上下文层次结构包含节点(NODE)和属性(Attribute)两类实体,可用于构建所有上下文变量。固定Context NODE节点被称为上下文根节点,在初始化控制器时自动创建,并始终具有固定属性。无论使用何种方法,均无法删除或修改上下文根节点。此节点是Web Dynpro框架中用于运行时数据存储的主要抽象类,可包含下级属性或其他节点。
一个NODE节点的所有子实体可聚集为一个单元,称为元素。NODE节点可看作此类元素的集合,就如表时行的集合一样。
属性(Attribute)是不能包含下级节点。
二、阐述节点(Node)属性 Cardinality 和 Supply Function 如何在运行时影响内存分配?
Cardinality-集合基数
33
每个上下文节点NODE均具有称为 基数 的属性。该属性由两个值组成,用于描述节点集合在运行时所存储的元素的最大和最小数量:
基数最小值: 0 0 或 1 1
基数最大值:1 1 或 n n
因此,可存在四个基数值(格式为 <最小值>..<最大值> ):
• 0..1:允许零个或一个元素
• 0..n:允许零个或多个元素
• 1..1:仅允许一个元素
• 1..n:允许一个或多个元素
所有节点都包括一个元素集合,即使是在集合中的元素最大数量限制为 1 的情况下。
上下文根节点始终仅包含一个元素(请注意基数为 1..1)。该元素称为缺省元素,且不可删除!仅当父集合包含至少一个元素时,才存在所有其它节点集合。因此,并不能保证运行时存在这些节点集合。于是,这些节点被称为相关节点。如果试图针对节点集合执行任何会违反其基数的操作,则 Web Dynpro 框架将出现运行时错误。此类操作包括:
• 试图删除基数为 1..<某值> 的节点的缺省元素
• 试图向基数为 <某值>..1 的节点添加另一个元素
提前选择(Lead Selection)
可使用从 1 开始的索引值来访问节点的元素集合。当制定提前选择Lead Selection时,只能将节点集合的一个元素标记为元素。上下文节点的提前选择可指向单个已选定的节点元素(提前选择值 = 已选节点元素数量),而在没有选定元素的情况下则包含常量 IF_WD_CONTEXT_NODE=>NO_SELECTION的值。如果将上下文节点属性 初始化提前选择(Initialization Lead Selection) 设置为 真 ,则Web Dynpro框架可自动设置提前选择。这种情况下,如果制定了提前选择,则集合的第一个元素将自动标记为元素。也可通过程序源代码设置提前选择,或通过 UI 元素相关的用户操作进行设置(例如,通过选择表视图元
素中与节点绑定的行)。
如果已设置提前选择,则可执行下列操作:
• 在控制器代码中,可使用特殊方法来访问节点的提前选择及其位置。
• UI 元素(如输入字段)可与该元素的属性进行绑定。
单例模式(Singleton)
属性设置为“假”,则对于父节点集合中的每个元素,都将具有一个独立的子节点实例。如果父节点中有 n 个元素,则该节点将具有 n 个单独的实例。
属性设置为“真”(缺省值),则父节点集合具有的元素数量将无足轻重。子节点将仅存在一个实例。
供应函数(Supply Function)
上例中,FLIGHTS 节点集合中可包含许多不同的元素。但是,因为单元集子节点 BOOKINGS 仅具有一个实例,所以我们需要确保在访问该子节点时,它包含父节点中已选定元素的正确数据。使用过程中有点类似 懒加载 的意思,只有当展示详细信息时,才调用供应函数去查询数据表,提交数据加载速度,节约内存占用。
供应函数是一种用于重新填充子节点的机制。可为控制器的每个上下文节点分配供应函数。当访问 无效上下文节点的数据时,运行时环境可自动调用该供应函数。在如下条件下可产生无效的上下文节点:
• 节点集合是初始的。
• 更改了父节点集合中的提前选择。
• 节点集合因编程方式而失效。
供应函数在结合单元集节点时极为有用。 单元集 类型的子节点元素的值取决于当前分配有提前选择的父节点的元素。如果用户更改了提前选择,则供应函数可访问新的提前选择元素,并重新相应地计算子节点元素的值。当定义或更改正文菜单中的上下文节点时,可输入供应函数的名称。因此,可生成带有给定签名的附加控制器方法:
• 父节点中提前选择元素上的参考可用于访问该元素的属性。
• 与供应函数相关的节点的参考可用于在子节点集合中存储相关数据。
三、不同控制器的Context node 映射
上下文映射允许控制器(通常为视图控制器)访问由某些其它控制器预处理的数据。因为映射关系允许直接参考其它控制器中的数据,所以无需复制或移动该数据。若要在两个控制器间建立上下文映射,目标控制器必须将源控制器声明为其属性中所使用的控制器。如果已在目标控制器的编辑模式下选中了 上下文 标签,则右侧会显示所有已使用的控制器的上下文。然后,可以按照下列方式参考源上下文的节点:
• 如果还未在目标控制器的上下文中定义要映射的独立节点,则可通过将该节点从源控制器上下文拖放到目标控制器上下文的根节点来映射源节点结构。
• 如果已经在目标控制器的上下文中定义了节点结构,则可将目标节点从目标控制器的上下文拖放到源控制器上下文中的映射源。但是对于相关节点而言,仅当已映射相关的独立节点时才能执行该操作。
内部映射是同一个组件界限内已映射节点和映射源节点间映射关系的名称。这表示在编写当前组件时,可建立完整的映射关系。