带有复选框的 vaadin8.1.0 网格有问题

vaadin8.1.0 Grid with Checkbox had an Issue

我正在使用 vaadin 8.1.0 网格。我需要将复选框作为列和列 header 插入。当我单击 header 列中的复选框时,应选中所有列的复选框。那工作正常。但问题是,如果我有 100 行,当我选中 header 复选框时,只有一些列复选框被选中,即只有显示的行。当我向下滚动时,未选中剩余的行复选框。这是我的代码:

    List<Person> people = new ArrayList();
         for (int i = 0; i < 1000; i++) {
          people.add(i, new Person("Galileo Galilei", 1564));
        }

    CheckBox CheckBox1 = new CheckBox("All");
    CheckBox1.setValue(false);

        Grid<Person> grid = new Grid<>();
        grid.setItems( people);
        grid.addColumn(Person::getName).setCaption("Name");
        grid.addColumn(Person::getYear).setCaption("Year of birth").setId("1");

        grid.addComponentColumn(Person -> {
            CheckBox chk=new CheckBox("Chk 2");
            CheckBox1.addValueChangeListener(e->
            chk.setValue(CheckBox1.getValue())
            );
            return chk; 
        }).setCaption("ch2").setId("CH2");

        grid.getHeaderRow(0).getCell("CH2").setComponent( CheckBox1);

嗯,出于性能原因,并非所有复选框都从一开始就呈现,正如您在下面的 GIF 中看到的那样(右侧,项目以紫色闪烁),只有当前可见的那些。当您滚动时,新项目将替换旧项目,并为它们绘制复选框。然而,它们的初始状态不会被选中,因此最简单的解决方案是将其初始状态设置为 master 复选框 之一:CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());.

结果:

此外,查看代码您可能有轻微泄漏。由于每次滚动较大的部分时都会绘制复选框,因此每次都会调用 grid.addComponentColumn 中的代码,并且值更改侦听器将不断地添加到列表中......因为它们永远不会未注册。看看下面的图片,经过一些滚动,我最终得到了 9000 多个:

为了解决这个问题,您可以在取消选中复选框时取消注册侦听器:

grid.addComponentColumn(Person -> {
     CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());
     // save the registration info to unregister at a later time
     Registration listenerRegistration = CheckBox1.addValueChangeListener(e -> chk.setValue(CheckBox1.getValue()));
     // when the checkbox is detached, remove the listener
     chk.addDetachListener(event -> listenerRegistration.remove());
     return chk;
 }).setCaption("ch2").setId("CH2");

现在列表只包含那些尚未分离的人:

您还可以通过布尔字段 "selected" 扩展数据模型或将其包装到新的 class 中并添加 "selected" 字段。然后 set/unset 将 ValueChangeListener 中的那个字段添加到 CheckBox。

这还将负责选择所有网格条目,而不仅仅是呈现的条目。您只需更改所有数据模型实例中的 "selected"。

另一种方法是使用 ImageRenderer。那么你就不必与任何听众打交道了。

这假设您的模型有一个属性来保存 checked/selected 的值。

ThemeResource resourceChecked = new ThemeResource("selected.gif");
ThemeResource resourceUnchecked = new ThemeResource("deselected.gif");

grid.addColumn(person -> person.getSelected() ? resourceChecked : resourceUnchecked, 
    new ImageRenderer<>(event -> { 
                Person person = event.getItem();
                person.setSelected(!person.getSelected());
                grid.getDataProvider().refreshItem(person);
                grid.markAsDirty();
            }));