2. Web Dynpro for ABAP 之 Component CONTROLLER(含有图片的PDF下载)
每个web动态Component包含一个Component CONTROLLER.这个 CONTROLLER是随着component的创建而自动创建起来的,其中包括context,事件和方法。不像view CONTROLLER,Component CONTROLLER对于Component中的所有的views是可见的。也就是说Component中的不同的views能够范根context元素和Component CONTROLLER的方法。所以说,Component CONTROLLER为Component内所有的view CONTROLLER自动创建起来。
如图所示:
关于Contenxt映射
Context 映射
如果你关联view 的context的节点到对应的Component CONTROLLER的context节点,Component CONTROLLER的context存储的数据,能够被view使用。这个过程叫做定义映射。
关于具体细节请看下面将要写的数据的绑定和映射。
下面的图形阐述了这个过程:
在view1的context根结点下有两个结点:
l 其中node1映射到了Component CONTROLLER的context的Node1结点。这意味着View1的node1的结构和Component CONTROLLER的node1的结构相匹配,或者说view1的结构包含在里面。在任何时间,view1的node1的属性值和对应的Component CONTROLLER的node1的的属性值相等。如果view1的context的node1属性值改变了,相对应的Component CONTROLLER的属性值也会发生改变,例如运行时人工输入了view输入框值,对应的Component CONTROLLER的context的值也相应改变。
l 节点Local Node View1,只被view1 CONTROLLER所拥有,并且只有View1的方法可以访问这个节点的属性值。
示例:扩展航班列表应用程序
以前的程序应用描述了呈现给用户的的view图形界面和对应的view CONTROLLER得到和保存数据的演示。View CONTROLLER的context和方法只能本地可见,即只在本view CONTROLLER里。所以其他的views不能够访问contents。为了能够访问view中的content,需要把数据和方法转移到Component CONTROLLER间接访问读取。下面的图形描述了Component的新的context结构,如图:
一旦Component CONTROLLER的context两个节点属性创建起来。View context相对应的节点能够映射到这两个节点。关于细节处理和限制信息,参考映射定义。当两个contexts中任何一个属性值做了改变,对应的contexts会自动改变。可以和其他的第二个views的context节点做对应于Component CONTROLLERcontext的节点映射,第二个view 的context也会随着映射的改变而改变。
接下来的扩展练习,flight 表中的数据已经传到了Component CONTROLLER,参考web dynpro abap的交叉控制方法。
定义映射
有许多方法可以定义view CONTROLLER的映射,大部分时候是通过view所对应的‘Context’定义。参考映射定义手册。
CONTROLLER方法编程
通常,属性和方法指定为web dynpro程序的处理过程,所需要的数据存储在context中。在action 事件处理和交叉 CONTROLLER方法调用中有了两个简单的程序处理示例。这里你会通过web dynpro架构中方法编程中学习到通用的信息,另外在经常用到的方法将会在程序代码中做描述。
当你创建了个新的web dynproComponent,Component CONTROLLER自动生成,同样,当你为Component创建了个新的view,view CONTROLLER也会自动的生成。每个Component窗口包含窗体 CONTROLLER,你可以为了实现需求创建定制化的 CONTROLLER。
对于每个 CONTROLLER,至少有个属性对象是自动生成的,名称如下:
l WD_CONTEXT
l WD_THIS
你还可以为每个 CONTROLLER创建你自己需要属性。这些属性用来存储非UI相关的应用数据(UI 相关的数据存储到了context).
Context节点常量
对于我们创建的 CONTROLLER的context上的每个节点,名字为WDCTX_<node name>常量在其对应的接口IG_<Conroller_name>和IF_< CONTROLLER_name>自动创建,在 CONTROLLER的源代码里面,这个常量可以用作节点名称从而代替字符文本,例如:
Wd_context->get_child_node( wd_this->wdctx_my_node ).
代替
Wd_context->get_child_node(‘MY_NODE’).
使用context节点常量的好处是编译器知道常量,从而减少语法错误,避免自己输入的context节点名称有时候不正确。当然,这个也允许手写传输文本,不用常量。
接口 CONTROLLER
接口 CONTROLLER在开发环境中并不是独立的对象,是Component CONTROLLER的一种特殊子集。
接口 CONTROLLER定义了供其他Component使用的web dynproComponent的接口。在Component CONTROLLER中,这些方法得到了实现。当我们在Component CONTROLLER中为methods/events/context的节点设置‘interface’标志时,这些元素将被拷贝到接口 CONTROLLER。
1) 引用变量 WD_CONTEXT
WD_CONTEXT是 CONTROLLER的context的属性。不管怎么做控制编辑,它总是类型为IF_WD_CONTEXT_NODE的引用变量。在 CONTROLLER方法中,我可以用WD_CONTEXT和接口方法编辑context 节点中的数据。
例如: CONTROLLER的context包含MY_TABLE_NODE节点。可以通过方法invalidate_table_node来验证节点元素的值。
Method invalidate_table_node.
Data: table_node type ref to IF_WD_CONTEXT_NODE.
Table_node = wd_context->get_child_node( ‘MY_TABLE_NODE’ ).
Table_node->invalidate().
Endmethod.
Get_CHILD_NODE和INVALIDATE 是接口IF_WD_CONTEXT_NODE的方法。其他经常用到的方法还包括GET_ATTRIBUTE和BIND_ELEMENT等等.
2) 引用变量WD_THIS和本地 CONTROLLER接口
每个 CONTROLLER包含一个本地接口,在 CONTROLLER中可以访问到。
控制其属性WD_THIS就是本地接口的一个引用,根据 CONTROLLER的不同,引用变量可以是以下类型:
l IF_COMPONENT CONTROLLER
l IF_<MY_CUSTOM_ CONTROLLER>
l IF_<MY_VIEW>
l IF_<MY_WINDOW>
通过这个引用变量可以访问本地 CONTROLLER接口的方法和属性。
l 包含所有的自定义的方法,这些方法是被程序员在当前 CONTROLLER创建和实现
程序员可以改变方法的实现,这些方法的位置在 CONTROLLER Editor的页签‘METHODS’中。通过双击方法名称可以跳转abap编辑器写代码。
l 程序员可以调用其他组中的方法,但不能够改变预先定义的方法的实现。
l 程序员可以实现第三方的方法组,这些方法只能在运行时调用。
l 所有的 CONTROLLER的属性的访问是通过引用变量WD_THIS实现的。
访问Web Dynpro运行时API
全局或者本地 CONTROLLER产生的接口都是有限的方法数量。只包含程序员直接或者间接定义或者实现的的方法和属性。所以Web Dynpro运行时为每个 CONTROLLER类型提供了泛型运行时API。在API中,经常用到的方法已经被实现,可以供程序员使用。你可以像Portal manager和message manager一样通过这些接口访问通用的函数。所有的泛型 CONTROLLER接口包含了方法WD_GET_API, 允许访问相应的运行时API.
View CONTROLLER的属性WD_COMP_ CONTROLLER
大部分情况,为一个View CONTROLLER声明Component CONTROLLER的用法是非常有用的。开发环境预先定义好了这些步骤。另外,每个View CONTROLLER已经包含了属性WD_COMP_ CONTROLLER,这个引用变量的类型是IG_COMPONENT CONTROLLER.在每个view CONTROLLER中,可以通过WD_COMP_ CONTROLLER访问Component所有公开的方法,即那些Component CONTROLLER产生的全局接口。
3) 本地控制接口的方法
注意:所有可以被改变的方法是那些被程序员实现的方法。在每个 CONTROLLER的‘Methods’页签中。当我们双击方法名字,将会转到ABAP编辑器,可以通过编辑代码实现方法体。
除了可以修改的方法外,每个 CONTROLLER的本地接口提供了许多只能被程序员使用但是不能被编辑的方法。这些方法什么时候是可用的方法,依赖于 CONTROLLER实现的状态和类型。
注意:由于所有的方法不能够被编辑,所以他们也不会显示在相对应的 CONTROLLER的‘Methods’ 页签中,作为接口的一部分,可以点击图标显示已经存在的方法。
如果你点击此按钮,当前使用的 CONTROLLER的接口将会单独在一个窗体中显示。也可以显示任何用到的 CONTROLLER接口。注意对于每个view CONTROLLER,相对应的component CONTROLLER会自动创建,一般会合适的创建出来。(当然也可以通过在属性WD_THIS的‘Attributes’页签中双击 CONTROLLER方法的引用参数接口类型IF_.........查看。)
钩子方法:运行时调用的方法
先前提到的应用方法,每个本地 CONTROLLER接口具有固定的数量的方法可以通过运。开发行时进行调用,开发人员不能指定什么时间方法被调用,但是能够修改实现,这些方法什么时间被调用是预定义好的。
WDDOINIT 和 WDDOEXIT
最简单的例子就是这两个方法:WDDOINIT和WDDOEXIT
当 CONTROLLER第一次初始化时调用方法WDDOINIT。对于每个新创建的 CONTROLLER,这些方法的方法体都是空的,但是可以写以下代码,例如
l 创建Help classes的实例
l 初始化 CONTROLLER属性(如果需要更多属性编程),还有引用变量可以初始化。
l 为 CONTROLLERcontext设置初始值。
示例:初始化 CONTROLLERcontext
Method wddoinit.
Data: node type ref to IF_WD_CONTEXT_NODE.
Data: Flights type spfli_tab.
*get node from context
Node = wd_context->get_child_node(‘CARRIER_NODE’).
*get connections from help class
Flights = cl_wd_get_spfli=>get_flights().
Node->bind_elements(flights).
Endmethod.
WDDOEXIT在退出 CONTROLLER的时候运行,可以用来释放锁。
对应的 CONTROLLER设置,本地 CONTROLLER接口包含的方法还有:
WDDOBEFORENAVIGATION,
WDDOPOSTPROCESSING,
WDDOMOFIFYVIEW.
本地 CONTROLLER接口的预定义方法
每个 CONTROLLER在运行时提供一些额外的方法集,可以用来开发应用程序。不像其他的控制其方法的实现,我们不能够改变其实现方法体。方法的内容依赖于 CONTROLLER类型和实现状态。其中的部分方法描述如下:
方法GET_<MY_USED_ CONTROLLER>_CTR
此方式是在本地 CONTROLLER接口里自动产生的,用于同一个Component里面的其他的 CONTROLLER,它不依赖于到底是viewComponent还是客户控件。
返回值
方法GET_<MY_USED_ CONTROLLER>_CTR总是返回用到的 CONTROLLER的component-global接口的引用变量,意思是返回值是一个类型为IG_<MY_USED_ CONTROLLER>的引用变量。
示例:
如果想在View CONTROLLER中使用客户定制的 CONTROLLERMY_CUST_ CONTROLLER全局接口的方法,可以在‘Properties’页签输入期望的客户 CONTROLLER,然后可以在本地接口的当前 CONTROLLER中使用方法GET_MY_CUST_ CONTROLLER_CTR。
Method my_ CONTROLLER_method.
Data: l_ref_my_cust_ CONTROLLER type ref to ig_my_cust_ CONTROLLER.
L_ref_my_cust_contrller = wd_this->get_my_cust_ CONTROLLER_ctr().
Endmethod.
注意:不同接口类型和在web dynpro Component接口可见性等详细信息,参考 CONTROLLERs of a web dynpro component.
在View CONTROLLER,相应的创建用法也是值的注意的。用法是当创建新的view时自动输入的. 类型为IG_COMPONENT CONTROLLER的引用变量也是自动创建出来的,即变量WD_COMP_ CONTROLLER.
这个变量是所有的view CONTROLLER所知道的。 是在view CONTROLLER的‘Attributes’页签中的,可以供程序员使用的。也就是说对应于Component CONTROLLER的所有的component-global接口的方法都是可用的。
更详细的信息参考Cross- CONTROLLER method call.
方法 WD_GET_API
这个方法包含所有的 CONTROLLER类型,关于此方法的使用和更详细的信心,参考以后要写的动态编程,请关注后续。
方法WD_CPUSE_<MY_COMPONENT_USAGE> 和WD_CPIFC_<MY_USED_COMPONENT>
对于使用在一个Component在另一个Component时特别重要。参考后续的component usage without CONTROLLER access或者component usage with CONTROLLER access. 当用到的Component的接口 CONTROLLER创建时或者使用Component时,每种 CONTROLLER类型都创建这些方法。
方法 FIRE_<MY_PLUG>_PLG
此方法只包含在View CONTROLLER和窗体 CONTROLLER中,在外部的插件在对应的 CONTROLLER里面有创建时使用。这个方法的作用是调用外部插件的view或者窗体启动。
示例:
Method my_ CONTROLLER_method.
Wd_this->fire_my_outbound_plg().
Endmethod.
更多信息参考后面的navigation.
方法 FIRE_<MY_EVENT>_EVT
这个方法允许每个Component CONTROLLER或者客户定义的 CONTROLLER里面定义的事件被触发。
事件和事件处理
我们可以为Component CONTROLLER定义一个事件让 CONTROLLER们进行交流。通过预定义的方法
FIRE_<MY_EVENT>_EVT可以触发这些事件。运行时一旦事件触发,在另一个 CONTROLLER的相应的事件处理程序将会自动调用。
Component CONTROLLER的使用必须输入到当前的 CONTROLLER去处理Component CONTROLLER的事件(Component CONTROLLER的使用会在view CONTROLLER自动创建)。
示例:下面的图形展示了Component CONTROLLER的方法在哪触发了事件MY_EVENT.
事件处理view CONTROLLER中的MY_HANDLER对应于事件MY_EVENT.因为Component CONTROLLER的事件配置给了View CONTROLLER中的event handler. 通过view CONTROLLER的‘Method’页签配置。
Cross-Component Events
可以使用Component CONTROLLER中的一个或者多个事件,用他们作为交叉事件。在 CONTROLLER中’Event’ 页签里面的’Interface’复选框选上。则对应的事件将会传输到Component接口,并且可以通过其他Component的事件处理访问到。(详情稍后有Cross-Component Program).
事件的参数(Parameter of Events)
事件有传输参数。可以通过Component CONTROLLER的‘Event’页签输入这些参数,并且制定类型。当在使用的 CONTROLLER创建了事件处理,并且把Component CONTROLLER的事件映射给他,则相应的参数自动的加到了处理事件的方法参数上。
示例:Component CONTROLLER
Component CONTROLLER方法中的事件被触发,创建的参数自动传输。
Events页签
Event
MY_EVENT
Parameter
MY_PARAMETER TYPE WDY_BOOLEAN
注意:WDY_BOOLEAN 是一个ABAP字典类型,具有bool变量功能。
X = true; space = false
Methods 页签
Method my_COMP_ CONTROLLER_method.
Wd_this->fire_my_event_evt(my_parameter = ‘X’).
Endmethod.
View CONTROLLER
事件处理起在view CONTROLLER中创建,并且赋值给事件MY_EVENT.事件处理器中的参数对应于MY_PARAMETER.
Methods 页签
Method Method Type Event CONTROLLER
My_EVENT_HANDER Event Hander MY_EVENT Component CONTROLLER
MY_EVENT_HANDER
Parameter Declaration Type Reference Type
WDEVENT Importing CL_WD_CUSTOM_EVENT
MY_PARAMETER importing WDY_BOOLEAN
Method my_event_handler.
Endmethod.
其他概念:用事件对象传输参数(Passing Parameters Using an event object)
每个事件处理方法自动被类型为CL_WD_CUSTOM_EVENT的参数WDEVENT感知。类接口CL_WD_CUSTOM_EVENT包含为WD_EVENT_PARAMETER类型的属性PARAMETERS和几个方法读取这个属性。
不去自动的添加事件处理参数给事件处理的方法,也不用静态给一个事件指定参数。我们还可以通过事件对象动态的指定参数。
意思是如果再设计的时候参数没有被静态的指定,可以通过事件处理方法的事件对象读取到,更多的详情请参下面要写的Dynamically Working with Parameter Mappings.
Supply Function
每个 CONTROLLER的context节点能够赋给一个supply function. 当context节点的数据被使用时,Supply function在运行时被调用。这就是当一个UI元素加载对应的数据第一次显示时的情况。通常当一个或者多个context节点的元素被访问时调用supply function.
l Context节点没有赋值或者初始状态
l 在以前的步骤中context元素被验证过
单独节点的Supply functions
对于单独节点的组合来说supply function特别有用。类型Singleton子节点元素的值取决于父节点的元素,即当前赋给的选择的这个父节点。如果用户改变了当前的选择(lead selection),supply function能够访问新的选中的节点下的元素,并且重新计算对应的子节点元素上的值。关于单独节点和多个context节点的信息,参考context nodes说明信息
下面的示例阐述怎样使用单独节点的supply function
示例:基于元素细节显示
所有可用的航空航线列表显示在一个table view中,叫做Carrier。做到这点,UI元素的table类型绑定到context节点,这个节点将View CONTROLLER的方法WDDOINIT中被初始化。方法在应用程序第一次执行时调用,table元素的数据第一次显示在屏幕上时,对于用户是可见的。
第二个table(Connections)显示指定的航空航班的所有的航班,通过第一个table中选定的航空航线的元素。用户可以在第一张表中选择任何行,然后显示对应的细节信息再第二个表中.第二张表必须根据对应的航空航线填充数据。但是对于每次选择,view不需要全部创建出来。
Context view 结构如下:
第一张表(Carrier)绑定到context节点CARRIER_NODE;第二张表Connections绑定到context节点CONNECTION_NODE.当第一次调用应用程序,WDDOINIT方法根据数据库表SCARR的数据填充到顶部节点(scarr表是所有航空公司航线的列表,包括ID,主页URL等)。Context节点的复选框选择自动创建在节点的第一个元素。表的上方位置航空公司航班是供选择的复选选择元素。
被选中位置的所有可用的航空公司航线航班将被列到表Connections。第二张表绑定到了context节点的CONNECTION_NODE,通过supply function GET_CONNECTIONS从数据库SPFLI得到。通过读取被选择的航空航线表中元素,所有对应的航班信息被显示出来:
当我们在Carrier表中选择其他的表元素作为首要选择的对象时,如下图
表Connections相对应的内容自动改变,如下图:
Context节点CONNECTION_NODE的supply Function
(Supply Function of the context node CONNECTION_NODE)
当通过CONNECTION_NODE的supply function读取选定的元素的CARRIER_NODE节点时,我们只能这样创建view.
Method get_connections.
Data: carr_attr type if_mainview=>element_carrier_node,
Flight type spfli_tab.
*get filled structure for parent node
Parament_element->get_static_attributes( importing
Static_attributes = carr_attr)
*get connections form help class
Flight = cl_wd_get_spfli=>get_flights_by_carrid(
Carrid = carr_attr-carrid).
Node->bind_elements( flights ).
Endmethod.
l 声明内部类型为spflif_tab内部变量和父节点CARRIER_NODE的context元素变量。
l 父节点CARRIER_NODE中被选中元素的参数值传输到内部变量CARR_ATTR.
注意:关于这传输,每个supply function用到参考类型为IF_WD_CONTEXT_ELEMENT的参数PARENT_ELEMENT.
PARENT_ELEMENT是当前节点的父节点的选中元素,的一个引用,参数自动显示在supply function的签字中。
l 此例子中,help class用来从数据库SPFLI中把数据导入到内标FLIGHTS中,用来导入对应的航空航班的连接数据。
l 最后,内表数据绑定到当前的context节点的CONNECTION_NODE,允许我们在屏幕中的表Connections显示对应的值.
每次当用户从表Carrier选择其他的表元素时作为选中状态,参数PARENT_ELEMENT的值相应改变,context节点CONNECTION_NODE的supply function被调用,属性值根据表Carrier中选中的行重新赋值。
注意:supply functions只能访问的内容数据包括
*包含在对应的当父节点
*包含在另外的节点,这个节点是相对于已经通过supply function填充数据节点的更高的层次。
注意:尽量避免supply function引起的异常或者通过方法调用的supply function引起的异常。因为supply function调用的频繁行,这些异常不能全部处理。
注意:supply functions单独在运行时调用,所以不能具体决定调用的时间。
如果相应的context节点内容被验证,supply function也会被调用。由于性能的原因,这需要做单独的检查。从技术角度看,每个节点均可以通过supply function填充。但是尽管如此,很少这样用。对于supply function的非正式的通过方法WDDOINIT和 CONTROLLER的时间处理。对于不同情况,会在不同的时间调用,所以调用的机制需要考虑去决定哪种方式可以使用。更多信息参见下面的Filling the Context.
应用程序开发中的公开方法(Free Methods of the Application Development)
作为程序员,我们可以为每个 CONTROLLER创建和实现自己的方法,这些方法典型的用途是读取和编辑数据。这些方法可以被程序员在 CONTROLLER中已经实现的其他的方法调用。
示例: 方法GET_FLIGHTS已经被实现从当前 CONTROLLER的后台读取数据。这些数据可以被同一个 CONTROLLER的第二个方法使用。
Method get_flights.
…
Endmethod.
Method fill_context_node.
Data: flightstruc type spfli,
My_node type ref to if_wd_context_node.
Flightstruc = wd_this->get_flights().
My_node = wd_context->get_child_node(‘MY_CONTEXT_NODE’).
My_node->bind_structure( new_item = flightstruc ).
Endmethod.
引用变量WD_THIS用来调用 CONTROLLER自定义的方法GET_FLIGHTS,并把返回值传给内部变量FLIGHT_STRUC.
下一步,context的节点MY_CONTEXT_NODE传给第二个变量类型为IF_WD_CONTEXT_NODE的MY_NODE。
最后一步绑定变量Flightstruc 到MY_NODE.
Component接口的公有方法(Free methods of the component interface)
我们在Component CONTROLLER创建和定义的每个公用方法能够加载到Component接口。在Component CONTROLLER的 ‘Methods’页签中选中复选框’Interface’,被选中的方法将成为Component接口 CONTROLLER的一部分,对于其他Component的 CONTROLLER是有效的。
(参见下面要写的Cross-Component Programming)
交叉 CONTROLLER方法调用(Cross- CONTROLLER Method Call)
Web Dynpro 架构允许程序员开发 CONTROLLER以外的源代码。以前的Action Event Handlers的例子可以解释这个过程:
注:在context映射中,在Component CONTROLLER中的交叉的view context需要映射到已经创建好的Component中。现在,action GO的事件处理的功能将被传输到Component CONTROLLER的方法。
Component CONTROLLER的方法(Method of the Component CONTROLLER)
下面的例子,方法SIMPLE_GET_FLIGHTS将被调用。
Method simple_get_flights.
Data:
Input_node type ref to IF_WD_CONTEXT_NODE,
TABLE_NODE TYPE ref to IF_WD_CONTEXT_NODE,
CAR type STRING,
FLIGHTS type standard table of spfli.
INPUT_NODE = WD_CONTEXT->GET_CHILD_NODE( ‘INPUT_NODE’ ).
INPUT_NODE->GET_ATTRIBUTE( exporting name = ‘IN1’
Importing value = CAR ).
FLIGHT = CL_WD_FLIGHT_MODEL=>GET_FLIGHTS_BY_CARID( CAR ).
TAB_NODE = WD_CONTEXT->GET_CHILD_NODE( ‘TABLE_NODE‘).
TAB_NODE->BIND_ELEMENTS( FLIGHTS).
Endmethod.
方法的内容不会改变,但是调用的方法改变了,意思是属性WD_CONTEXT是本地context的引用,不再是view的context,而是Component CONTROLLER的context.
在View CONTROLLER事件处理中的Component CONTROLLER的方法的调用(Method Call of the Component CONTROLLER in the Event Hander of the View- CONTROLLER)
Component CONTROLLER中的新创建的方法先现在必须被view CONTROLLER中的Action GO的事件处理调用。
Method ONACTIONGO.
Wd_COMP_ CONTROLLER->simple_get_flights().
Endmethod.
WD_COMP_ CONTROLLER的属性是参考类型为IG_COMPONENT_CONTROLLER的引用变量,所以引用了对应的Component Controller。会自动被Component中的每个vIew Controller感知到。
4) Web Dynpro运行时APIs
程序员可以使用web dynpro 的APIs来进行高效设计控制器编程的。APIs可以通过几种方法访问,关于架构的类和接口的详细清单以及其方法,参考相关资料。
对于不同的编程方面应用,运行时接口提供了多种方法,包括:
l 通过访问窗体管理器API IF_WD_WINDOW_MANAGER来根据存在的web dynpro窗体创建弹出窗口
l 通过API IF_WD_PORTAL_INTERGRATION可以访问portal集成。
l Context 处理
l 创建messages
通过动态编程,有.更多方面的应用,例如:
l 动态操作布局
l 动态浏览控件
访问运行时API的示例(Example for Accessing a Runtime API)
不同的控制器类型的动态运行时API已经在引用变量WD_THIS中提到过。依赖于控制器的类型。本地控制器接口的方法WD_GET_API的返回值是接口的引用变量。
l IF_WD_VIEW_CONTROLLER(应用于所有的View控制器)
l IF_WD_COMPONENT(应用于所有的component controllers)
l IF_WD_CONTROLLER(应用于所有的接口控制器或者客户化的控制器)
提示:下面的例子是访问本地控制器类型的运行时API的代码示例,此处的本地控制器指的是View控制器。
Method MY_VIEW_CONTROLLER_METHOD.
Data: l_runtimeapi type ref to IF_WD_VIEW_CONTROLLER.
L_RUNTIMEAPI = WD_THIS->WD_GET_API().
Method.
上述的示例方法中,可以通过属性L_RUNTIMEAPI使用运行时API IF_WD_VIEW_CONTROLLER的方法.
提示:也可以访问使用着的控制器类型的运行时API,例如
Method MY_CONTROLLER_METHOD.
Data: l_comp_intf type ref to ig_componentcontroller,
L_runtimeapi type ref to if_wd_component.
L_comp_intf = wd_this->get_componentcontroller_ctr().
L_runtimeapi = l_comp_intf->wd_get_api().
Endmethod.
上例中,部件控制器的component-global接口的引用变量被创建。部件控制器的运行时API的引用变量通过方法WD_GET_API也被创建起来。
提示:由于类型IG_COMPONENTCONTROLLER的WD_COMP_CONTROLLER属性已经在开发环境中为每个view controller创建起来,所以访问部件控制器的运行时的API的代码就相对少多了,如下:
Method my_view_controller_method.
Data: l_runtimeapi type ref to IF_WD_COMPONENT.
L_RUNTIMEAPI = WD_COMP_CONTROLLER->WD_GET_API().
Endmethod.
所有的其他的运行时web dynpro APIs通过不同的方式可以进行访问。其中两个例子:
l API IF_WD_VIEW能够通过本地view控制器接口的WDDOMODIFYVIEW方法的VIEW属性进行 独立的访问。
l API IF_WD_CONTEXT_NODE和IF_WD_CONTEXT_NODE_INFO可以通过IF_WD_CONTEXT类型的WD_CONTEXT属性进行访问。需要对属性设置固定值。
更多的纤细的类和接口的可访问的方法,可以参考SAP官方相应的文档。
5) 为context赋值 Filling the Context
在Web dynpro for abap变成中,content元素的值有着举足轻重的地位。所以,不管是给context赋值还是改变其中的值,必须周全的考虑。可以根据以下的方法来决定什么时间赋值或者更新context。
WDDOINIT
方法WDDOINIT是控制器的初始方法。Context在先前只是做了赋值操作,后来并没有做验证,此方法就是对应的给context赋值的操作。对于action和对应的事件处理而发生的相关的数据更新,也可以使用这个方法。
注意:对于那些必须要赋值的context节点,只能通过WDDOINIT进行赋值。
关于在此方法中给context赋值调用的顺序相对于supply function有点复杂。因为调用没有连接到context节点,对应的节点作为引用必须首先被创建出来。
Method WDDOINIT.
Data: node type ref to if_wd_context_node,
Flights type spfli_tab.
*get node from context
Node = WD_context->get_child_node(‘CARRIER_NODE’).
*get connections from help class
Flights = cl_wd_get_spfli=>get_flights().
Node->bind_elements(flights).
Endmethod.
Supply Function
如果需求要求节点的内容必须可用时,通过supply function给context赋值也是非常有用的。下面是单独节点的赋值的例子。当相关的节点元素被访问时,supply function就会被调用,从技术的角度看,通过supply function给context赋值是最简单的方法,因为相对应的节点已经作为一个参数可以使用了(查看上文的Supply Function)。
注意:当通过supply function更新数据的时候,我们总是重新创建全部的context节点(我们不能通过supply function给context中的独立的元素赋新值)。这样会降低Web Dynpro应用程序的性能(看下文的性能因素分析)。
Action事件处理(Action Event Handlers)
用户经常需要在Action对context进行赋值和更新的响应,这种情况下, 需要对action的事件处理方法中的context进行编程,通常有两种选择:
第一种选择情况:事件处理只是对节点进行验证,所以supply function会被自动调用。事件处理方法就会认为对应的supply function的实现已经存在了。
第二种选择情况:事件处理自己赋值context(我们必须确定保证事件处理方法没有绑定到指定的context节点,在WDDOINIT方法中,作为参数填充的节点不会直接可用,但是必须在先前的程序中按步骤创建起来)。
注意:不管怎样用我们选择的方法赋值context,下面的规则必须遵循:当在源代码中用string指定节点的名字或者属性的名字时,必须用大写字母。
Context的性能 ( Performance of the context)
既然为context提供了多种可选的设计,可能会有很多分割的下对象,必然是动态的,所以需要能很好的控制web dynpro应用程序的性能。
6) 阶段模型Phase Model
目的
本节提供请求数据传输的处理的信息。
注:第一个请求只包含了读取元数据的描述和用户接口的初始显示。
本阶段模型中的某些点,程序员可以通过动态编程改变用户界面。
处理流
下面图形有条理的描述了数据传输的处理流程
下图更细节的描述了事件处理流程:
数据从客户端传输到数据容器 (Data Transport from Client to Data Container)
用户输入的数据从客户端传输到数据容器。数据容器用作临时的数据存储,所以,在数据容器中的数据只有在运行时环境下才有效,并非在对应用开发者。
验证用户输入( Validation of the User Input )
所有的用户输入都要被检查,如果发现输入有误,并不会中断检查,剩下的数据的传输不会中断,如果数据类型是正确的数据,甚至错误的数据也会被传输到context.
检查中,下面的检查/转换将被执行
l 类型匹配检查(如输入数据字段中不允许有字幕)
l 用户特定的转换(如数据根据用户的设置进行相应的格式调整)
l 数据字典的检查/转换
l 大写转换
l 退出转换
l 当context节点的数据像数据字典参考货币字段时,也会进行这样的校验
l 检查属性集的值设置
对于每个包含错误的的信息输入会产生一个错误信息,在数据传到Controller context后,将会显示出来。
数据从数据容器传输到Context(Data transport from the data container to the context)
此步骤后,现在的数据已经可以被应用程序使用了。
WDDOBEFOREACTION
Action触发之前,我们可以通过这个方法执行我们自己的验证。这个方法只对View Controllers有效。用来让component里所有的可见的views赋值给当前阶段的模型实例,这些包含了所有的嵌入的components.
Actions和事件的处理(Handling of Actions and Events)
此步骤独立执行,完成数据容器和context之间的数据传输。 当用户输入的数据在验证时发现是错误的,相对应的错误信息将显示,应用开发人员就会能够更正数据。
通常,有两种不同的event handlers类型(参看event handling的细节图形):
l 当用户输入的信息通过验证没有错误发生时,标准的event handlers将被调用。
l 当验证的时候产生错误信息,独立的验证event handlers将被调用。在这种情况下,相应的错误信息创建出来,但是不显示。
导航有可能被event handler触发,即event handler被调用从而触发导航。
WDDOBEFORENAVIGATION
在这种处理情景中,方法WDDOBEFORENAVIGATION用来进行这些controller contexts的验证,这些在应用程序中需要的数据在请求/响应的循环中还没有被验证。这对于某些特定的复杂的Web Dynpro应用程序非常重要。此方法只能用在component controller. 这个方法用来将部件赋给情景模型实例和所有的嵌入的component.
在先前事件处理的步骤中,如果错误出现了,导航步骤将被中断。我们还可以通过调用接口IF_WD_COMPONENT的CANCEL_NAVIGATION方法来中断导航。在请求/响应循环中通过这个方法调用先前的全部应用程序的导航。导航的请求在随后的情景示例中将被删除,必须被重新初始化。
导航和初始化随后的View (Navigation and Initialization of the subsequent view)
正在执行的事件触发了导航。随后的内部的部件view将被调用,对应的事件处理将被处理。
View Modification
一旦View对应的方法WDDOINIT在运行时执行了,则相应的View将被创建,应用程序开发人员可以修改View的UI tree,例如,动态的增加元素节点。
方法WDDOMODIFYVIEW用在本演示示例的相关部件的所有的可见的views和嵌入的部件。
WDDOPOSTPROCESSING
此方法是在最后的处理过程被调用,所以,你可以在这里添加需要清空的处理逻辑代码。
Rendering
在翻译过程中,用户界面将显示在屏幕上,即UI tree的结构和元素上的数据将被呈现出来。注意:由于翻译,所有的views数据将被迭代出显示。对应的context可能只会在rendering的时候被填充。也会用到supply function的调用。程序员应该保证在supply function中没有异常产生。
Popups
对于每个激活的窗体,一个演示阶段模型的实例都存在,意思是说,每个阶段模型实例只能分给一个准确的窗体和部件。
当打开一个内部的弹出(弹出有Web Dynpro context),增加的一个模型实例自动创建。 弹出的实例是异步于当前激活的窗体的模型实例后面打开的,最新的模型实例弹出以后,内部的弹出窗体同样也会异步的关闭。最后,当前激活的窗体的模型实例再次启动。
7) 客户端实现
下面的图形给我我们一个客户端实现的大体概念:
依赖于选择的翻译设备,Web Dynpro的核心部分和特定的实现的客户端在运行时共同工作。就浏览器情况来说,是在服务器端编译的(SSR server-side rendering).
SSR 替代了它同客户端设备的交互工作。当用eCATT时,客户端通过它的XML版本实现,数据和格式单独分别传输(不同于浏览器)。
View的元素在用户接口的元素库中,也是Web 用户接口。
在web dynpro for abap编程中,浏览器总是用做解释设备。数据,时间和布局信息再服务端转换成HTML 和JavaScript,并且一起传输过来。在浏览器下,大部分的工作已经在服务器端完成,整个布局放到了服务器端。例如浏览器自己不去做太多的工作,只是保证能够响应树节点删的节点能够打开和关闭。
当在web dynpro运行时被调用时,特殊的适配器技术用来转换数据,事件作为请求响应循环的一部分等转变成浏览器合适的格式,例如HTML,JavaScript,XML等。相反的情况,页面的数据也会转变成适合ABAP对象的数据。
3. Web Dynpro for ABAP 之
Web Dynpro Window
& Web Dynpro Application