关于主菜单打开一个已经打开的页面的疑问

在多标签模式下通过主菜单打开了A,B,C三个界面。这个时候不管当前标签页是否是B,如果再去点击主菜单打开B。发现B界面重新加载了。按说这个界面已经打开过了,直接选中该标签页就行了,为啥整个界面好像重新创建了,用户输入的数据,选中的行等等状态全部丢失了。这不符合默认的使用习惯吧?是要设置什么选项吗?

印象中之前提到这这个问题:(:grinning: , 看一下这个属性:
cuba.web.mainTabSheetMode

和这个没关系啊,怎么设置都不对

按默认的设置就有问题,您可以稍微试一下。原来提的问题是标签页切换之后会销毁重建,但是状态都不会丢弃,现在切换标签页不会有问题。现在的问题是点主菜单发送切换标签页的时候,状态全丢,这太不友好了。

哦,是这个问题。

从源码看现在是这种行为, 不过应该可以扩展。

1 . 从 ScreenCommand 继承一个类:ExtScreenCommand,覆盖这个类的 run 方法。在这个方法中增加检测界面是否已经打开的逻辑。

2 . 扩展 MenuItemCommands Bean,覆盖
MenuItemCommand create(FrameOwner origin, MenuItem item) 方法。 对于 screen 类型的菜单重新创建自定义的 ScreenCommand.
return new ExtScreenCommand(origin, item, item.getScreen(), item.getDescriptor(), params, properties);

先这样试试,有问题再沟通。

好的,感谢,我先试试

发现通过扩展WebScreens类,重写showFromNavigation里的逻辑即可实现。现在有个问题就是判断出screen已经在标签页中,如何调用代码让标签页选中这个界面呢?能给点思路吗?

成了

@Override
    public OperationResult showFromNavigation(Screen screen) {
        LaunchMode launchMode = screen.getWindow().getContext().getLaunchMode();

        if (launchMode == OpenMode.NEW_TAB
                || launchMode == OpenMode.NEW_WINDOW) {
            WebAppWorkArea workArea = getConfiguredWorkArea();

            if (workArea.getMode() == AppWorkArea.Mode.SINGLE) {
                Collection<Screen> currentBreadcrumbs = workArea.getCurrentBreadcrumbs();

                if (!currentBreadcrumbs.isEmpty()) {
                    Iterator<Screen> iterator = currentBreadcrumbs.iterator();
                    OperationResult result = OperationResult.success();

                    // close all
                    while (result.getStatus() == OperationResult.Status.SUCCESS
                            && iterator.hasNext()) {

                        Screen previousScreen = iterator.next();
                        result = previousScreen.close(NAVIGATION_CLOSE_ACTION);
                    }

                    if (result.getStatus() != OperationResult.Status.SUCCESS) {
                        // if unsaved changes dialog is shown, we can continue later
                        return result.compose(() -> showFromNavigation(screen));
                    }
                }
            } else {

                ScreenStack sameScreen = getTabbedScreensStacks(workArea)
                        .filter(windowStack -> windowStack.getBreadcrumbs().size() == 1) // never close non-top active screens
                        .map(windowStack -> new ScreenStack( windowStack.getBreadcrumbs().iterator().next(),windowStack))
                        .filter(screenStack -> isAlreadyOpened(screen, screenStack.screen))
                        .findFirst()
                        .orElse(null);
                //如果screen已经打开则直接选中
                if (sameScreen!=null){
                    sameScreen.stack.select();
                    return  OperationResult.success();
                }else {
                    if (isMaxTabCountExceeded(screen)) {
                        showTooManyOpenTabsMessage();
                        return OperationResult.fail();
                    }
                }

//                if (!UiControllerUtils.isMultipleOpen(screen)) {
//
//
//                    if (sameScreen != null) {
//                        OperationResult result = sameScreen.close(NAVIGATION_CLOSE_ACTION);
//                        if (result.getStatus() != OperationResult.Status.SUCCESS) {
//                            // if unsaved changes dialog is shown, we can continue later
//                            return result.compose(() -> showFromNavigation(screen));
//                        }
//                    }
//                }
            }
        }

        return show(screen);
    }

建议向官方反馈一下,默认的行为其实很怪异,一般都是打开过的界面直接切换。

1赞