web dynpro for ABAP采用了MVC的设计方法。一个web dynpro component包括windowviewscomponent controllerwindowview主要和UI有关。windows只是一种容器,在一个component内一个window可以包含任意多个view,而component controller只有一个。如果一个component不需要view,那么windows也就相应无需存在了。

一个web dynpro component可以与一个URL关联,通过浏览器来访问,或者作为另一个web dynpro componentsub-component供调用。

web dynpro componentcontroller分为四类:

component controller:这种类型的controller在一个web dynpro component内只存在一个,并且没有visual interface

custom controller:这类controller是可选的,用于封装component controllersub-function

view controller:每一个view都有一个对应的view controller,负责与视图有关的逻辑,如检查用户的输入和处理user action

window controller:一个window内只存在一个window controller,用于通过inbound plugs传递数据。

web dynpro 中有两个常提到的概念是context mappingdata binding。每个controller内部都会有一个context,用于存储controller所用的数据。context mapping提供了一种机制,供不同的controller之间交换数据。context mapping分为internalextern两种。如果同一个component内的不同controller之间共享数据,这被成为internal context mapping;共享数据的controller不在同一个component之内,这被称为extern context mapping。要注意的是view controller一类不能作为context mapping的源,否则就违背了MVC的设计原则。data binding为数据在contexUI元素之间自动(双向)传递提供支持。

接下来再看看context这个东西。context是一个包含nodeattribute的结构。每个context都有一个默认的root node,这个root node不能被修改或删除。一个node可以包含子元素(nodeattribute),而attribute只能依附于其他nodecontext root node而存在。在同一个context内,每个node的名字必须是唯一的。一个node连同其子元素被合称为一个element

context中的每个node都有两个重要的property

cardinality:这个属性给出了当前node collection在运行时(runtime)包含的元素数目的最小值和最大值。这个属性的取值包括0..1(仅允许01个元素),0..n(允许0或更多元素),1..1(仅允许一个元素),1..n(允许一个或多个元素)。

singleton:这个属性决定了子节点在实例化时是singleton还是不是singleton,因此它的值就是布尔值。在课程中在讲singleton时还提到了supply function,两者常在一起使用以实现lazy data instantiation。比如在加载一个包含多行的表时,每一行包含的更详细数据不会被首先加载,而只有在用户选中并查特定行时,与该行相关的数据在会被读取。

定义user interface相对比较简单,从左边栏的工具箱里拖拽需要的UI elementslayout里面,并设置各个UI element的属性。更多的工作是关于data binding

有些UI elements是不可见的,如TransparentContainer, ViewUIElementsContainer。这类元素用于组织其他的可见元素,如Button, LabelInputFieldTableTree等。所有的UI elements被组织成一个树状结构,根节点名为RootUIElement,类型为TransparentContainerRootUIElement下的每个container element都有一个属性Layout,它规定了在container内元素的布局。4layout manager可供layout属性选择:

FlowLayout
Rowlayout
MatrixLayout
GridLayout

如果一个UI element被绑定到了一个context内的nodeattribute,那么这个node/attribute的值就会被赋给这个UI element。当UI element的值发生变化时,这种变化也会自动反映到context中的node/attribute上。这就是前面已经提及的data binding。这种绑定只能发生在同一个viewcontextview controller之间。当想改变一个UI element的行为时,只需修改与这个UI element绑定的node/attribute

UI elementsTextViewLabelCaption被用于显示文字。当这类UI elements被绑定到attribute,而attribute是与data dictionarydata element有关。这时这个data element的相应文字会被用于这个UI element。另一种情况是,a Label is related to a InputField, and the Text property of the Label is left blank. The label text then originates from the data element related to the InputField.

Composite UI Elements

有的UI element由多个基本的UI elements组成,如Table(由多个TableColumn构成)。每个TableColumn又由一个Caption和一个Cell editor(默认为TextView这种类型的UI)组成。Table这类UI element只能被绑定到cardinality0..n1..nnode。每个Table有一个属性selectionMode,有6个不同的值来控制行的选择,具体参见文档第86 - 87页。

web dynpro中每个controller都有两个默认的方法:

wddoinit():这是一个controller内第一个被调用的方法,常用于初始化数据。

wddoexit():这是一个controller内最后一个被调用的方法,用于做收尾工作。

这两个方法在controller被创建时自动生成,并且都是空的方法。

对于component controller还有两外两个重要的方法:

wddobeforenavigation():
This method is called after the action method has been processed and just before the web dynpro frameworkprocesses the events in the navigation queque.

wddopostprocessing():
This method allows data validation from multiple components, and it's the last controller method that is processed before the UI is sent to the client.

view controller也有自己的两个方法:

wddobeforeaction():
After the web dynpro application has been started and the user has raised a client event, the first methods to be processed in the wda are the wddobeforeaction() methods of all view controllers of the previous rendered view assembly, before the action handler method to the event processed.

webdomodifyview():
用于动态修改UI Element

对于各类controller,用户都可以创建自己的methods。在创建method时,有三种类型可选:method, event handlersupply function。双击方法名就可以打开一个编辑器,书写实现代码。在一个component内,一个controller可以调用其他controller的方法,只要在这个controller内声明使用了另一个controller即可。如果要让一个controller的自定义方法能被位于component内的另外一个controller调用,那么需要设置该方法的Interface属性。

前面提到了controllermethods,现在轮到controllerattributes。除了interface controllerinterface view controller外每个controller都有两个预定义好的attributeWD_THISWD_CONTEXTWD_THIS指向当前的controller interface IF_<controller name>WD_CONTEXT指向controller context下的root node。访问context内的其他node/attribute就是借助它来完成的。

如果一个controller声明使用component controller,那么一个标准attribute WD_COMP_CONTROLLER会被自动创建,以指向component controller,这样component controller内的methodspublic attributes就能被调用,wd_comp-controller -> method name

如果一个controller A声明使用其他类型的controller B(不是component controller),这时在controller A中不会自动生成一个指向controller B的引用。为了得到指向B的引用需要下面的办法:

DATA: lo_ctrl TYPE REF TO ig_<ctrl>.
lo_ctrl = wd_this->get_<ctrl>_ctrl( ).

用户也可以自定义attribute。如果attributepublic flag被设置,那么这个attribute对于同一个component内的其他controller也是可见的。访问其他controllerpublic attribute的方式与访问method一样。

访问一个context node

对于每一个controller,系统都会为其自动创建一个interface,名为IF_<ctrol_name>。在这个interface中,对于每一个context node都会有一个相应的WDCTX_<node_name>存在。访问root node直接使用WD_CONTEXT,访问root node的子node使用get_child_node( )方法,要注意的是方法名作为参数被传递时必须是大写!方法返回指向指定node的引用,类型为IF_WD_CONTEXT_NODE。这个方法还有一个可选参数,是要访问的element在父node中的索引编号。

访问一个node element

获得一个指向node的引用后就可以使用get_element( )方法来获得指向element at selection的引用,类型为IF_WD_CONTEXT_ELEMENT

DATA: lo_nd_flights TYPE REF TO lf_wd_context_node.
DATA: lo_el_flights  TYPE REF TO if_wd_context_element.

lo_wd_flights = wd_context->get_child_node( name = wd_this->wdctx_flights ).

*get element at lead selection
lo_el_flight = lo_flight_flights->get_element( ).

*if lead selection is not set, ELEM_FLIGHTS will be initial
IF ( lo_el_flights IS INITIAL ).
...
ENDIF.

要获得索引为nelement,使用方法get_element( index = n )get_element_count( ) 方法返回一个collection中的element的数目。

访问单个nodeattribute

一旦获得了指向一个node element的引用,就可以使用下面两个方法来访问这个nodeattributeget_attribute( )可以访问任意一个attribute,所需的参数是要访问的attribute的名字。另一个方法是get_static_attributes( ),用于访问static defined attributes(此处不明白)。

DATA: lo_nd_flights TYPE REF TO lf_wd_context_node.
DATA: lo_el_flights  TYPE REF TO if_wd_context_element.
DATA: lv_connid TYPE wd_this->element_flights-connid.

lo_wd_flights = wd_context->get_child_node( name = wd_this->wdctx_flights ).
lo_el_flight = lo_flight_flights->get_element( ).

*get single attribute
lo_el_flights->get_attribute(
EXPORTING
name = 'CONNID'
IMPORTING
value = lv_connid ).

controller context中的每个nodeinterface IF_<ctrl_name>中都有一个隐含的名为element_<node_name>structure和名为elements_<node_name>standard internal table,其line typeelement_<node_name>。这个internal table用于存放multiple node elementsattributes。(此处不明白,既然每个node都有一个这样对应的internal table,为什么还说存放multiple node elementsattributes??)

一个使用get_static_attributes( )访问一个node static attributes的例子:
DATA: lo_nd_flights TYPE REF TO lf_wd_context_node.
DATA: lo_el_flights  TYPE REF TO if_wd_context_element.
DATA: ls_flights TYPE wd_this->element_flights.

lo_nd_flights = wd_context->get_child_node( name = wd_this->wdctx_flights ).
lo_el_flights = lo_nd_flights->get_elements

*get all static declared attributes
lo_el_flights->get_static_attributes(
IMPORTING
static_attributes = ls_flights ).

获取所有node elementsstatic attribues

DATA: lo_nd_flights TYPE REF TO lf_wd_context_node.
DATA: lt_flights TYPE wd_this->element_flights.

lo_nd_flights = wd_context->get_child_node( name = wd_this->wdctx_flights ).

*get all static declared attributes for all node element
lo_nd_flights->get_static_attributes_table(
IMPORTING
table = lt_flights ).

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐