1.上下文的定义
Web Dynpro中的Context即程序的上下文。在Web Dynpro工程中,除了接口视图控制器以外的所有控制器和视图都有一个存储数据的多级结构,而这就是Web Dynpro中的上下文。
从宏观对象的角度理解,上下文可以看作视图对象对应的逻辑属性,或者是视图对象的环境变量,所有前端页面的数据交互都会通过上下文传递到对应的控制器中进行逻辑处理。另外,它还有以下几个特点:
●所有上下文中的数据仅存在于控制器的实例中,一旦实例运行结束,上下文中的数据也将会被释放。
●上下文的结构是在开发阶段定义的,程序运行时无法对其进行任何更改。
●视图的上下文是私有的,但组件控制器的上下文可以通过对外声明进行公开,也可以进行映射,如控制器与视图的上下文映射,控制器与模型的上下文映射等,这也是Web Dynpro中严格进行MVC架构的一个体现。
从底层代码的分析可以发现,上下文源自IPrivate<NAME>View接口的静态内部类,所有在可视化界面中对上下文的操作都会间接地去修改该静态类,并动态地生成对应该上下文数据结构的操作方法。假设创建了一个视图,则它的上下文来自于IPrivate<NAME>View接口中的IContextNode静态类。下面通过一个开发实例进行进一步讲解和验证。
开发实例:
1)切换到新建的视图,在“Properties”中单击“Context”,如图3-16所示。
图3-16 单击“Context”
图3-17 创建新特性
注:在NetWeaver 7.0及其之前版本的开发工具中,上下文Context的定义在与布局“Layout”并列的“Context”中,然而在新版本的开发工具中,上下文、方法、事件处理器等内容统一被包含在“Properties”选项卡下。
2)右击“Context”,在弹出的快捷菜单中选择“New”→“Attribute”命令,创建新特性,如图3-17所示。
3)选择自定义创建,然后输入特性名称并选择特性的类型。选中“Manually”单选按钮进行手动创建,并输入“name”,选择“string”字符串类型,如图3-18所示。
图3-18 输入特性名称并选择特性类型
4)验证上下文在Java源文件中定义。切换到IPrivateDynp02CompView类,通过Outline方法清单或按<Ctrl+O>组合键找到IContextElement静态类,可以看到刚才新建的属性对应的静态对象声明(见图3-19)以及get和set赋值方法都已自动创建完毕(见图3-20)。
图3-19 静态对象声明
5)通过代码对Context进行赋值,右击对应的视图,选择打开Java编辑器,如图3-12所示。
图3-20 自动创建的方法
图3-21 打开Java编辑器
6)找到视图初始化的默认“wdDoInit”方法,并加入以下赋值代码:
7)找到“onActionButton”方法,给之前的代码加上注释并加入以下代码:
//将默认Context元素中的name属性的值取出并赋给name变量
String name=wdContext.currentContextElement().getName();
//将name变量以成功消息形式打印出来
wdComponentAPI.getMessageManager().reportSuccess(name);
8)保存所有修改,重新编译运行之后,即可进行相关测试。单击“Button”按钮可以看到打印出的“name”特性的信息,如图3-22所示。由于是成功类型的消息,因此文本前有一个绿色的感叹号。
图3-22 程序运行效果
2.上下文的属性
由于上下文是可分级的数据,因此不管是上下文的结点或者特性,都可以对它们的属性进行进一步的配置。下面通过上一节创建的实例进行进一步说明。
(1)特性的属性
打开页面的“属性”选项卡,找到刚才创建的name特性,单击选中后,可以看到右边还有相关的属性可以进行配置,如图3-23所示特性的属性名称及说明见表3-1。
图3-23 特性的属性配置
表3-1 特性的属性名称及说明
(2)结点的属性
上下文Context中的结点是存放Web Dynpro数据的一个虚拟类,它允许有子结点(包含了结点和特性两种类型),所以它也可以看作一个集合,可以想象是一个表格或者树的根结点。结点属性名称及说明见表3-2。
表3-2 结点的属性名称及说明
下面对结点的集合属性和选择的集合属性中的下拉列表的选项进行说明。
1)Collection Cardinality中:
①0..1代表node集合长度为1,默认集合为空,可以添加一个实例。
②0..n代表node集合长度为n,默认集合为空,可以添加n个实例。
③1..1代表node集合长度为1,初始化默认一个实例,不可以再次添加实例。
④1..n代表node集合长度为n,初始化默认一个实例,可以添加n个实例。
2)Selection Cardinality中:
①0..1代表最多一条的选中,默认没有选中条目。
②0..n代表最多n条的选中,默认没有选中条目。
③1..1代表最多一条的选中,默认一条选中。
④1..n代表最多n条的选中,默认n条选中。
开发实例:
1)右击Context,在弹出的快捷菜单中选择“New”→“Node”命令,新建一个结点,如图3-24所示。
图3-24 新建一个结点
2)输入结点名称“Per”,单击“Finish”按钮,如图3-25所示。
图3-25 输入结点名称
3)接着验证Context在Java文件中的定义:在保存好上述修改后,切换到“Internal Dynp02CompView”类,可以看到静态语句块中自动生成了对刚才新建node的初始化代码如图3-26所示。其中参数中的CMICardinality分别对应于结点的集合属性和可选属性。
图3-26 自动生成代码定义
4)打开页面的“属性”选项卡,找到刚才创建的“Per”结点,单击选中后,可以看到右边还有相关的属性可以进行配置,如图3-27所示。
5)通过代码对结点中的特性进行赋值。在“Per”结点中新建一个名称为“id”的特性,如图3-28所示。
图3-27 结点的属性
图3-28 新建一个名称为“id”的特性
6)作为测试用例,将“Per”结点的集合属性修改为“0..1”,如图3-29所示。
图3-29 结点属性示例
7)切换到视图的“wdDoInit”初始化方法,加入以下代码:
wdComponentAPI.getMessageManager().reportSuccess("PerNode Size:"+wdContext.nodePer().size());//打印结点的大小
IPerElement createAndAddPerElement=wdContext.nodePer().createAndAddPerElement();//添加Element
createAndAddPerElement.setId("12");
wdComponentAPI.getMessageManager().reportSuccess("PerNode Size:"+wdContext.nodePer().size());//打印添加Element后node size
8)进入“Button”按钮的动作处理逻辑中,并加入以下代码:
messageManager.reportSuccess(wdContext.nodePer().currentPerElement().getId());
//打印当前选中(默认选中)Element的Id变量值
9)与之前同样地进行编译部署,在运行之后,单击“Button”按钮,如图3-30所示。
10)接着单击“Button”按钮,打印出添加的特性值。
图3-30 运行效果
图3-31 单击按钮后的效果
(3)特性的可计算属性
特性的属性中的Calculated比较特别,除了true或者false的选择外,还涉及代码编写,所以在此单独进行说明与开发实例展示。该属性设置为true时,代表可以自定义特性值的获取逻辑,从字面理解来看也就是可以计算的意思,并且在对应的类中会生成对应的getter方法。
开发实例:确认自动生成的公共方法及其调用逻辑
1)切换到视图的上下文界面,将“Per”结点下的“id”特性的Calculated属性设置为“true”,如图3-32所示。根据上下文类定义的介绍,依次查看视图控制器Dynp02Comp View.java、公共接口InternalDynp02CompView.java和实现类IPrivateDynp02 CompView.java 3个java文件中自动生成的代码。
图3-32 特性的属性
2)单击“Calculated Getter”中“getPerId”最右侧的“Go”按钮,界面将自动跳转到Dynp02CompView.java中生成的getPerId()公共方法(见图3-33),传入参数element是“Per”结点的实例元素。
图3-33 自动生成的代码1
3)进入InternalDynp02CompView.java,同样看到生成了getPerId()方法(见图3-34),内部实现为调用Dynp02CompView实例的方法。
图3-34 自动生成的代码2
4)进入IPrivateDynp02CompView.java,定位到IPerElement内部类,看到wdGetCalculat⁃ed()方法中添加了执行InternalDynp02CompView实例中getPerId()方法的代码,如图3-35所示。由于InternalDynp02CompView中getPerId()方法执行Dynp02CompView中getPerId()逻辑,因此最终是执行了视图控制器中的自定义代码。
图3-35 自动生成的代码3
开发人员一般关注视图控制器的java文件即可,如Dynp02CompView.java,而接口类和实现类的代码都会自动生成。
开发实例:验证getter方法的执行时间与执行顺序
1)切换到Dynp02CompView类中的getPerId()方法(见图3-36),并添加以下代码:
wdComponentAPI.getMessageManager().reportSuccess("Execute getPerId Method");
图3-36 添加自定义代码
2)修改node Per的集合属性为1..1、Initialize Lead Selection为true(见图3-37),同时注释掉wdDoInit()中的代码,进入Button Action并修改为以下代码:
图3-37 结点属性设置(www.daowen.com)
3)保存所有修改,并重新编译、运行之后,即可进行相关测试,运行效果如图3-38所示。
单击“Button”按钮,可以看到先打印Execute语句后打印Id Value,系统在执行current∗Element.getId()方法前,执行了getPerId()方法,并且最终Id的数据源来自getPerId代码逻辑。由于getPerId()返回为null,因此打印的Id值为null。
图3-38 运行效果1
4)修改getPerId()代码逻辑,保存所有修改,并重新编译,运行之后,即可进行相关测试。
5)单击“Button”按钮,程序返回了Id所属的当前Element索引以及自定义的拼接字符串,如图3-39所示。
图3-39 运行效果2
3.上下文的相关API及常用方法
1.IContextNode上下文默认结点相关公共方法
切换到IPrivate<NAME>View,定位到内部类IContextNode的公共方法,如图3-40所示。
图3-40 定位到内部类IContextNode的公共方法
1)createContextElement():创建一个该结点类型的上下文元素(element),但结点的索引并不能指向该元素的引用,即无法在结点中找到该元素,需要在代码中另外对结点的实例执行add方法进行添加,所以一般使用下面的createAndAdd方法。
2)createAndAddContextElement():创建一个上下文元素并添加至对应的结点实例中,即结点的集合属性的大小增加了,并且可以通过getElement()方法或currentElement方法(当前元素)获取该条Element的索引。注:集合属性为“1..1”的结点不允许执行createAndAddElment()方法,因为这样的结点有且仅有一个元素。
3)currentContextElement():获取当前首选(Lead Selection)的元素,只有结点存在首选元素时,该方法才能获取对应的元素,以下为currentContextElement在不同属性下的获取值情况:
当Initial Lead Selection为false时,并且结点在没有Lead Selected的情况下,currentCon⁃textElement始终返回为空。
当Initial Lead Selection为false时,并且结点在有Lead Selected的情况下,currentContex⁃tElement返回当前已选中的元素。
当Initial Lead Selection为true时,并且结点在没有Lead Selected的情况下,始终返回第一条元素。
Node<NAME>():获取<NAME>名称的子结点的引用。
current<NAME>Element():返回<NAME>名称的子结点对应的当前元素。
create<NAME>Element():创建一个<NAME>名称的子结点的元素。
createAndAdd<NAME>Element():创建一个<NAME>名称的子结点的元素,并将引用添加至子结点中。
2.IContextElement上下文默认结点元素的相关公共方法
1)get<NAME>():IContextElement下定义的特性get方法,获取<NAME>名称的特性值。
2)set<NAME>():IContextElement下定义的特性set方法,设置<NAME>名称的特性值。
3.I<NAME>Node自定义结点的相关公共方法
1)current<NAME>Element():同IContextNode,返回<NAME>名称的子结点对应的当前元素。
2)create<NAME>Element():同IContextNode,创建一个<NAME>名称的子结点的元素。
3)createAndAdd<NAME>Element():同IContextNode,创建一个<NAME>名称的子结点的元素,并将引用添加至子结点中。
4)get<NAME>ElementAt():该方法针对集合属性为0..n或1..n的结点,获取指定索引的元素。
4.I<NAME>Element自定义<NAME>结点元素(可以看作<NAME>结点的实例)的相关公共方法(见图3-41)
图3-41 结点元素相关公共方法
1)get<NAME>():同IContextEle⁃ment,获取<NAME>名称的特性值。
2)set<NAME>():同IContextEle⁃ment,设置<NAME>名称的特性值。
以上整体介绍了默认上下文的ICon⁃textNode、IContextElement以及自定义结点的I<NAME>Node、I<NAME>Element的相关API的说明。而从IContextNode的初始化方法可以看到,该Node其实是集合属性为1..1,并且选择属性也为1..1的结点,因此通常把它叫作根结点,可以在根结点的基础上去构造符合个性化需求的结构化上下文,并且这些数据结构会在IPrivate<NAME>View的内部类中自动生成对应的公共方法。当然这些新的内部类以及类方法同样遵循上述的规则,并以此类推控制整个上下文及其结构。
从Web Dynpro开发组件的角度来理解,Context是具体某一DC组件的上下文,通过对上下文的操作来实现对整个组件的属性控制。上下文中所有结点结构都对应于后台的内部类,并且针对内部类有对应的构造与操作变量的方法。
开发实例:
(1)上下文属性实例1
1)修改“Per”结点的集合属性为“0..1”,同时修改Initial Lead Selection属性为“false”,如图3-42所示。
图3-42 设置结点属性
2)切换到wdDoInit()方法,保留以下代码(见图3-43):
图3-43 代码修改
3)双击“Button”按钮,进入按钮事件的逻辑处理,并保留以下代码(见图3-44):
图3-44 代码修改
4)保存所有修改,并重新编译、运行之后,即可进行相关测试,如图3-45所示。
5)单击“Button”按钮进行测试,运行效果如图3-46所示。
图3-45 初始化运行效果
图3-46 运行效果
可以看到打印的Message为null,即currentPerElement()方法获取的是Lead Selection的条目,当Lead Selection为false时,该方法返回的是空指针。
(2)上下文属性实例2
1)切换到Context视图,设置node Per的Initialize Lead Selection属性为“true”,如图3-47所示。
图3-47 设置结点属性
2)保存所有修改,并重新编译、运行之后,即可进行相关测试,单击“Button”按钮,运行效果如图3-48所示。
从上面的结果可以看到,currentPerElement()返回的值不为空,修改打印的代码可以打印出currentElement的Id属性值。
图3-48 运行效果
(3)上下文属性实例3
1)切换到Context视图,修改“Per”结点的集合属性为“0..n”、Initialize Lead Selec⁃tion属性为“false”,保存所有修改,并重新编译、运行之后,即可进行相关测试,如图3-49所示。
图3-49 设置结点属性
2)单击“Button”按钮就能看到对应的提醒消息,current<NAME>Element()返回的为空,如图3-50所示。
图3-50 单击“Button”按钮后的运行效果
(4)上下文属性实例4
1)再次修改Initialize lead Selection为“true”,保存所有修改,并重新编译、运行之后,即可进行相关测试,如图3-51所示。
图3-51 设置结点属性
2)单击“Button”按钮,可以看到currentElement返回的不为空,同时指向了对node第一条Element的引用,如图3-52所示。
3)切换到OutLine视图,右击“RootElement”,在弹出的快捷菜单中选择“Apply Tem⁃plate”,选项,如图3-53所示。
4)在弹出的对话框中选中“Table”类型,单击“Next”按钮,如图3-54所示。
图3-52 单击“Button”按钮后的运行效果
图3-53 应用模板菜单选择
图3-54 模板类型选择
5)选中“Per”结点和属性Id,单击“Next”按钮完成创建,如图3-55所示。
图3-55 选择对应上下文
6)适当调整生成Table_0的宽度,如图3-56所示。
图3-56 设置表格属性
7)切换到wdDoInit()方法,并添加以下代码(见图3-57):
createAndAddPerElement=wdContext.nodePer().createAndAddPerElement();
createAndAddPerElement.setId("13");
图3-57 添加自定义代码
8)保存所有修改,并重新编译、运行之后,即可进行相关测试。初始化时,打印的node Size值为2,Table_0默认选中第一条,运行效果如图3-58所示。
图3-58 运行效果
9)单击“Button”按钮后,消息打印出一条Element的引用,如图3-59所示。
图3-59 单击“Button”按钮后的运行效果
10)选中表格第二条行项目,并单击“Button”按钮,如图3-60所示。
图3-60 选择表格
11)单击“Button”按钮,运行效果如图3-61所示。
图3-61 单击“Button”按钮后的运行效果
此时current<NAME>Element指向对第二条Element的引用,即当Table_0的Selection Mode为单选时(如果Selection Mode属性为auto,则表格控件的选择模式由绑定的数据结构决定,上下文结点“Per”的选择属性为“0..1”,所以表格选择模式默认为单选),针对表格行项目的单击动作会对表格的首选项属性“Lead Selection”进行相应修改,随后current<NAME>Element返回修改后的首选项属性所指向的行项目的引用。
12)修改node Per的selection cardinality为0..n、Initialize lead selection为false,同时切换到Outline→Table_0→Properties→Selection Mode,并设置为multiNoLead(multiNoLead为多选模式,但选中行项目时不设置Lead Selection),重新编译、部署,运行程序。从运行的结果可以看出,在上下文结点的“Initialize Lead Selection”为false,同时以该结点为数据源的表格选择模式设置为∗No Lead时,current<NAME>Element返回始终为空,即结点并没有被赋值为lead selected的元素,运行效果如图3-62所示。
图3-62 修改后的运行效果
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。