Abap 将视图实例动态添加到透明容器

Abap 将视图实例动态添加到透明容器,abap,webdynpro,Abap,Webdynpro,我有一个场景,我想在一个视图上创建一个视图的N个实例到透明容器,每个实例接收不同的参数。为了实现这一点,我编写了一些逻辑来动态创建cl\u wd\u视图\容器\元素,将其添加到cl\u wd\u uielement\容器(主视图上的透明容器),然后使用动态导航触发一个插头来发送我的参数。代码可以在下面找到 这一切都有一个问题:创建的实例不是唯一的,所以我基本上添加了相同视图的N个副本。N个插件被触发和处理,但最后一个为所有视图设置参数,因为只有一个实例。视图的WDDOMODIFYVIEW也只触发

我有一个场景,我想在一个视图上创建一个视图的N个实例到
透明容器
,每个实例接收不同的参数。为了实现这一点,我编写了一些逻辑来动态创建
cl\u wd\u视图\容器\元素
,将其添加到
cl\u wd\u uielement\容器
(主视图上的
透明容器
),然后使用动态导航触发一个插头来发送我的参数。代码可以在下面找到

这一切都有一个问题:创建的实例不是唯一的,所以我基本上添加了相同视图的N个副本。N个插件被触发和处理,但最后一个为所有视图设置参数,因为只有一个实例。视图的
WDDOMODIFYVIEW
也只触发一次

下面的代码被重新调整用途并从工作版本中清理出来,所以我知道这是可能的。最大的区别是,我在场景中添加了来自同一个WDC的视图。在原始应用程序中,动态添加的视图有自己的Web Dynpro组件,调用方还提供动态创建的组件用法

有没有办法创建我缺少的多个实例?在这种情况下,我到底应该提供一个组件用法吗?我已经对此进行了几个小时的修补,但没有取得任何进展,所以我欢迎任何意见让我走上正轨

主视图中的代码:

DATA:
    lo_container          TYPE REF TO cl_wd_uielement_container,
    lo_subview            TYPE REF TO cl_wd_view_container_uielement,
    lo_flow_data          TYPE REF TO cl_wd_flow_data,
    lo_view_controller    TYPE REF TO if_wd_view_controller,
    lo_component_usage    TYPE REF TO if_wd_component_usage,
    lo_wdr_view           TYPE REF TO cl_wdr_view,
    lo_component_api      TYPE REF TO if_wd_component,

    lt_posts              TYPE ztt_fi_vernot_posts,
    ls_post               LIKE LINE OF lt_posts,
    lt_parameters         TYPE wdr_event_parameter_list,
    ls_parameter          TYPE wdr_event_parameter,

    lv_view_id            TYPE string,
    lv_source_plug_name   TYPE string,
    lv_target_embed_pos   TYPE string,
    lv_param_value        TYPE REF TO DATA.
FIELD-SYMBOLS:
    <lv_param_value>      TYPE bu_partner
.

lt_posts = wd_this->mo_model->get_posts( iv_open = abap_true ).
" Retrieve and refresh the view container.
lo_wdr_view  ?= wd_this->wd_get_api( ).
lo_container ?= lo_wdr_view->root_element.
lo_container ?= lo_wdr_view->get_element( 'TC_POSTS' ).
lo_container->remove_all_children( ).
LOOP AT lt_posts INTO ls_post.
" View and plug IDs should be unique.
CONCATENATE 'POSTS_' ls_post-index  INTO lv_view_id.
CONCATENATE 'OUTPLUG_' ls_post-index INTO lv_source_plug_name.
" Create a new view.
lo_subview  = cl_wd_view_container_uielement=>new_view_container_uielement( id = lv_view_id ).
lo_flow_data = cl_wd_flow_data=>new_flow_data( element = lo_subview ).
lo_subview->set_layout_data( lo_flow_data ).
lo_subview->set_layout_data( cl_wd_flow_data=>new_flow_data( element = lo_subview ) ).
lo_container->add_child( lo_subview ).
lo_view_controller = wd_this->wd_get_api( ).
CONCATENATE 'V_MAIN/' lv_view_id INTO lv_target_embed_pos.
*   This was present in the source, returning a component usage via create_comp_usage_of_same_type()
*   lo_component_usage = wd_comp_controller->get_component( iv_compcnt = ls_post-index  ).

lo_view_controller->prepare_dynamic_navigation(
  source_window_name          = 'W_MAIN'
  " Found in the window structure for this View
  source_vusage_name          = 'V_MAIN_USAGE_0'
  source_plug_name            = lv_source_plug_name
" target_component_name       = '[WDC name]'   " Optional?
" target_component_usage      = lo_component_usage->name " Optional?
  target_view_name            = 'V_POSTS'
  target_plug_name            = 'SET_PARAMS'
  target_embedding_position   = lv_target_embed_pos ).

" Fill the paramaters. Note that the values should be passed as pointers.
REFRESH lt_parameters.
CLEAR ls_parameter.
ls_parameter-name = zcl_fi_vernot=>gcs_plugs-params-bp.
CREATE DATA lv_param_value LIKE ls_post-bp.
ASSIGN lv_param_value->* TO <lv_param_value>.
<lv_param_value> = ls_post-bp.
ls_parameter-value = lv_param_value.
INSERT ls_parameter INTO TABLE lt_parameters.

" Do the same for the contract.
CLEAR ls_parameter.
ls_parameter-name = zcl_fi_vernot=>gcs_plugs-params-contract.
CREATE DATA lv_param_value LIKE ls_post-contract.
ASSIGN lv_param_value->* TO <lv_param_value>.
<lv_param_value> = ls_post-contract.
ls_parameter-value = lv_param_value.
INSERT ls_parameter INTO TABLE lt_parameters.

" Finally, fire the plug.
wd_this->wd_get_api( )->fire_plug( plug_name = lv_source_plug_name parameters = lt_parameters ).

ENDLOOP.
数据:
lo_容器类型参考cl_wd_UIU元素容器,
lo_子视图类型参照cl_wd_视图_容器元素,
lo_flow_数据类型参考cl_wd_flow_数据,
lo_view_控制器类型参考if_wd_view_控制器,
lo_组件使用类型参考if_wd_组件使用,
lo_wdr_视图类型参照cl_wdr_视图,
lo_组件\u api类型参考if_wd_组件,
lt_支柱类型ztt_fi_vernot_支柱,
L_柱状lt_柱线,
lt\u参数类型wdr\u事件\u参数\u列表,
ls_参数类型wdr_事件_参数,
lv\U视图\U id类型字符串,
lv\u源\u插头\u名称类型字符串,
lv\u目标\u嵌入\u位置类型字符串,
lv_参数值类型参考数据。
字段符号:
类型bu_合作伙伴
.
lt_posts=wd_this->mo_model->get_posts(iv_open=abap_true)。
“检索并刷新视图容器。
lo_wdr_视图?=wd_this->wd_get_api()。
lo_容器?=lo_wdr_视图->根元素。
lo_容器?=lo_wdr_视图->获取元素('TC_POSTS')。
lo_容器->删除所有子容器()。
将lt_柱循环到ls_柱。
“视图和插头ID应该是唯一的。
将“POSTS”ls\u post-index连接到lv\u view\u id中。
将“outpug”ls\u post-index连接到lv\u源\u插件\u名称中。
“创建一个新视图。
lo_子视图=cl_wd_视图_容器_uielement=>新的_视图_容器_uielement(id=lv_视图_id)。
lo_flow_data=cl_wd_flow_data=>new_flow_data(元素=lo_子视图)。
lo_子视图->设置_布局_数据(lo_流量_数据)。
lo_子视图->设置_布局_数据(cl_wd_flow_数据=>新建_flow_数据(元素=lo_子视图))。
lo_容器->添加子对象(lo_子视图)。
lo_view_controller=wd_this->wd_get_api()。
将“V_MAIN/”lv_view_id连接到lv_target_embed_pos。
*这在源代码中存在,通过创建相同类型的组件使用返回组件使用
*lo_component_usage=wd_comp_controller->get_component(iv_compcnt=ls_post-index)。
lo\u查看\u控制器->准备\u动态\u导航(
source\u window\u name='W\u MAIN'
“在该视图的窗口结构中找到
source_vusage_name='V_MAIN_用法\u 0'
source\u plug\u name=lv\u source\u plug\u name
“目标组件名称='[WDC名称]'”可选?
“target\u component\u usage=lo\u component\u usage->name”可选?
target_view_name='V_POSTS'
target_plug_name='SET_PARAMS'
目标嵌入位置=lv\U目标嵌入位置)。
“填充参数。请注意,值应作为指针传递。
刷新lt_参数。
清除ls_参数。
ls_parameter-name=zcl_fi_vernot=>gcs_plugs-params-bp。
创建数据lv_param_值,如ls_post-bp。
将lv_参数值->*分配给。
=ls_后bp。
ls_参数值=lv_参数值。
将ls_参数插入表lt_参数。
“对合同也这样做。
清除ls_参数。
ls_parameter-name=zcl_fi_vernot=>gcs_plugs-params-contract。
创建数据lv_param_值,如ls_post-contract。
将lv_参数值->*分配给。
=ls_后合同。
ls_参数值=lv_参数值。
将ls_参数插入表lt_参数。
“最后,打开插头。
wd\u this->wd\u get\u api()->fire\u plug(plug\u name=lv\u source\u plug\u name parameters=lt\u parameters)。
结束循环。

此问题不仅限于动态生成视图,而且当您希望在同一组件的窗口中多次使用特定视图时也会出现。只创建一个实例,因此重用非常有限


唯一的解决方案是将视图分离到自己的Web Dynpro组件,或者创建活动WDC的多个组件用法,并在动态导航中使用这些组件。

请提供一个示例代码?我们尝试了您的解决方案,但没有成功。@Dorad恐怕不行。这已经快四年了,而且不仅仅是我不再有权访问这个系统了吗?IIRC我从来没有真正解决过最初的问题,而是解决了它。正如在这个回答中提到的,真正的解决方案可能是创建组件用法并将它们传递出去,但我怀疑这是一个编写代码的杂务和维护的噩梦,我从来没有真正进行过测试坦白地说,在这一点上,尝试在WD中做任何事情,甚至是远程复杂的事情,都是一个迹象,表明你应该转向Fiori。如果你必须使用它,我会提出一个新问题。