2017-08-02 1 views
0

Je travaille avec la grille vaadin 8.1.0. J'ai besoin d'insérer une case à cocher en tant que colonne et aussi en tant qu'en-tête de colonne. lorsque je clique sur la case à cocher dans l'en-tête de colonne, toutes les cases à cocher doivent être cochées. Cela fonctionne bien. Mais le problème est que si j'ai 100 lignes, quand je vérifie l'en-tête de l'en-tête, seules certaines cases à cocher de la colonne sont vérifiées, c'est-à-dire, seulement les lignes qui sont affichées. Lorsque je fais défiler les lignes restantes, les cases à cocher ne sont pas cochées. Voici mon code:vaadin8.1.0 Grille avec Checkbox avait un problème

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); 
+0

Qu'advient-il si vous aussi 'chk.setValue (CheckBox1.getValue())' après avoir créé la case à cocher dans votre colonne de composants (à part déjà fait la valeur d'écoute de changement)? – Morfic

+0

Avez-vous essayé grid.setSelectionMode (SelectionMode.MULTI); au lieu d'utiliser votre propre case à cocher. –

+0

Oui j'ai essayé SelectionMode Mais mon besoin est différent, je n'ai pas besoin de sélectionner la ligne. – Apoorva

Répondre

0

Eh bien, pour des raisons de performance, pas toutes les cases à cocher sont rendus dès le début, comme vous le verrez dans le GIF ci-dessous (à droite, éléments clignotants en violet), juste ceux actuellement visibles. Et lorsque vous faites défiler, de nouveaux éléments remplaceront les anciens, et des cases à cocher seront dessinées pour eux. Cependant, leur état initial ne sera pas pris en compte. La solution la plus simple consiste donc à définir son état initial sur celui de la case principale : CheckBox chk = new CheckBox("Chk 2", CheckBox1.getValue());.

Résultat:

rendering-of-the-checkboxes

De plus, en regardant le code que vous pourriez avoir une fuite mineure. Puisque les cases à cocher sont dessinées chaque fois que vous faites défiler une section plus grande, le code grid.addComponentColumn sera appelé à chaque fois, et les écouteurs de changement de valeur seront ajoutés à la liste encore et encore ... car ils ne sont jamais désinscrits. Jetez un oeil à l'image ci-dessous, après quelques parchemins, je me suis retrouvé avec plus de 9000 d'entre eux:

value change listeners accumulating

Pour y remédier, vous pouvez désenregistrer les auditeurs lorsque les cases à cocher sont détachés:

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"); 

maintenant, la liste ne contient que ceux qui ne sont pas encore détaché:

smaller-list-of-listeners

+0

Merci Ça a marché pour moi. – Apoorva

+0

@Apoorva vous êtes les bienvenus. J'espère que vous avez également vu et pris en compte le peu d'accumulation des auditeurs et comment vous pouvez les désinscrire. – Morfic

0

Vous pourriez al donc étendez le modèle de données par un champ booléen "sélectionné" ou enveloppez-le dans une nouvelle classe et ajoutez le champ "sélectionné". Ensuite, définissez/désélectionnez ce champ dans le ValueChangeListener ajouté au contrôle CheckBox.

Ceci prendra également soin de sélectionner toutes les entrées de la grille et pas seulement celle qui a été rendue. Vous devrez juste changer "sélectionné" dans toutes vos instances de modèle de données.

0

Une autre approche consisterait à utiliser ImageRenderer. Ensuite, vous n'auriez pas à traiter avec des auditeurs.

Ceci suppose que votre modèle a un attribut pour contenir la valeur de cochée/sélectionnée.

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(); 
      }));