0

Vaadin 8.1 引入了该TreeGrid组件。它不再具有collapseItemsRecursivelyandexpandItemsRecursively方法(在现在的旧Tree组件中可用)。我错过了什么还是您需要开发自己的实现?如果是这样,推荐的方法是什么?

4

2 回答 2

2

我相信您已经注意到,TreeGrid 是一个相当新的组件,目前正在开发并从 v8.1.alphaX 开始可用(当前稳定版本是 v8.0.6)。因此,它可能暂时只有一些基本功能,其余的将在未来的某个时候推出,尽管不能保证。例如,自 2011 年以来,对旧版 TreeTable 组件的类似功能请求一直处于打开状态。

Vaadin 文档警告

无论哪种方式,即使它们可能不是最佳解决方案,您也可以使用一些变通方法来实现此行为。我无耻地将TreeGrid 的 vaadin-sampler 中当前可用的代码的略微修改版本用作基本示例。

public class RecursiveExpansionTreeGrid extends VerticalLayout {

    private Random random = new Random();

    public RecursiveExpansionTreeGrid() {
        // common setup with some dummy data
        TreeGrid<Project> treeGrid = new TreeGrid<>();
        treeGrid.setItems(generateProjectsForYears(2010, 2016), Project::getSubProjects);
        treeGrid.addColumn(Project::getName).setCaption("Project Name").setId("name-column");
        treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done");
        treeGrid.addColumn(Project::getLastModified).setCaption("Last Modified");
        addComponent(treeGrid);
    }

    // generate some dummy data to display in the tree grid
    private List<Project> generateProjectsForYears(int startYear, int endYear) {
        List<Project> projects = new ArrayList<>();

        for (int year = startYear; year <= endYear; year++) {
            Project yearProject = new Project("Year " + year);

            for (int i = 1; i < 2 + random.nextInt(5); i++) {
                Project customerProject = new Project("Customer Project " + i);
                customerProject.setSubProjects(Arrays.asList(
                        new LeafProject("Implementation", random.nextInt(100), year),
                        new LeafProject("Planning", random.nextInt(10), year),
                        new LeafProject("Prototyping", random.nextInt(20), year)));
                yearProject.addSubProject(customerProject);
            }
            projects.add(yearProject);
        }
        return projects;
    }

    // POJO for easy binding
    public class Project {
        private List<Project> subProjects = new ArrayList<>();
        private String name;

        public Project(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public List<Project> getSubProjects() {
            return subProjects;
        }

        public void setSubProjects(List<Project> subProjects) {
            this.subProjects = subProjects;
        }

        public void addSubProject(Project subProject) {
            subProjects.add(subProject);
        }

        public int getHoursDone() {
            return getSubProjects().stream().map(project -> project.getHoursDone()).reduce(0, Integer::sum);
        }

        public Date getLastModified() {
            return getSubProjects().stream().map(project -> project.getLastModified()).max(Date::compareTo).orElse(null);
        }
    }

    // Second POJO for easy binding
    public class LeafProject extends Project {
        private int hoursDone;
        private Date lastModified;

        public LeafProject(String name, int hoursDone, int year) {
            super(name);
            this.hoursDone = hoursDone;
            lastModified = new Date(year - 1900, random.nextInt(12), random.nextInt(10));
        }

        @Override
        public int getHoursDone() {
            return hoursDone;
        }

        @Override
        public Date getLastModified() {
            return lastModified;
        }
    }
}

接下来,递归扩展或折叠节点取决于您的场景,但基本上它分解为同一件事:确保从根到最深叶的每个节点都展开/折叠。最简单的方法是展平您的层次结构到节点列表中,并调用适当的方法,expand(List<T> items)或者expand(T ... items)(第二个委托给第一个,可能是一种方便的方法,例如expand(myItem))。

为简单起见,我在我们的实现中添加了一个flatten方法。Project如果由于某种原因您不能这样做,则创建一个递归方法,该方法创建一个从所选节点开始的列表,并包括所有子节点、子节点、子节点......好吧,你明白了。

public Stream<Project> flatten() {
    return Stream.concat(Stream.of(this), getSubProjects().stream().flatMap(Project::flatten));
}

可能的场景:

  1. 扩展根时自动扩展整个层次结构 - 添加侦听器,并展开/折叠整个扁平层次结构:
treeGrid.addCollapseListener(event -> {
    if (event.isUserOriginated()) {
        // event is triggered by all collapse calls, so only do it the first time, when the user clicks in the UI
        // and ignore the programmatic calls
        treeGrid.collapse(event.getCollapsedItem().flatten().collect(Collectors.toList()));
    }
});
treeGrid.addExpandListener(event -> {
    if (event.isUserOriginated()) {
        // event is triggered by all expand calls, so only do it the first time, when the user clicks in the UI
        // and ignore the programmatic calls
        treeGrid.expand(event.getExpandedItem().flatten().collect(Collectors.toList()));
    }
});
  1. 使用自定义操作(例如上下文菜单)扩展层次结构或其中的一部分
GridContextMenu<Project> contextMenu = new GridContextMenu<>(treeGrid);
contextMenu.addGridBodyContextMenuListener(contextEvent -> {
    contextMenu.removeItems();
    if (contextEvent.getItem() != null) {
        Project project = (Project) contextEvent.getItem();
        // update selection
        treeGrid.select(project);

        // show option for expanding
        contextMenu.addItem("Expand all", VaadinIcons.PLUS, event -> treeGrid.expand((project).flatten().collect(Collectors.toList())));

        // show option for collapsing
        contextMenu.addItem("Collapse all", VaadinIcons.MINUS, event -> treeGrid.collapse((project).flatten().collect(Collectors.toList())));
    }
});

最后,你应该得到这个效果:

TreeGrid - 递归展开或折叠

于 2017-07-05T21:16:14.833 回答
0

treegrid 的文档中,您可以使用方法,collapse并且expand,通过传递 treegrid 数据项的列表或数组来展开或折叠:

treeGrid.expand(someTreeGridItem1, someTreeGridItem2);
treeGrid.collapse(someTreeGridItem1);

同样值得注意的是,有一个部分显示了防止某些项目被折叠的能力

于 2017-07-05T18:34:04.350 回答