title: JavaFX TableColumn with ObservableList as value
body: <p>In my <code>TableView</code>, one of the <code>TableColumn</code> values is an <code>ObservableList</code>. To simplify things, it only contains <code>StringProperty</code> values. In my cell value factory for the column, I am concatenating the values together using the <code>Bindings</code> class.</p>
  
  <p>The result I'm wanting should be a <code>StringExpression</code> that updates whenever the <code>ObservableList</code> changes.</p>
  
  <p>The problem I'm having is that when any of the values of the list change, the generated <code>StringExpression</code> updates correctly, though when I add or remove values to the list, it will not update.</p>
  
  <p>My first thought was to add a <code>ListChangeListener</code> to the row, but this seems impractical since there could be dozens or hundreds of rows to the table.</p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  import javafx.application.Application;
  import javafx.beans.binding.Bindings;
  import javafx.beans.property.SimpleStringProperty;
  import javafx.beans.property.StringProperty;
  import javafx.beans.value.ObservableValue;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.event.ActionEvent;
  import javafx.event.EventHandler;
  import javafx.scene.Scene;
  import javafx.scene.control.Button;
  import javafx.scene.control.TableColumn;
  import javafx.scene.control.TableColumn.CellDataFeatures;
  import javafx.scene.control.TableView;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.layout.HBox;
  import javafx.stage.Stage;
  import javafx.util.Callback;
  
  public class TestFx extends Application {
  
      @Override
      public void start(Stage primaryStage) {        
          //Note, I never really see this "row" value directly, they're loaded 
          //in from a database, and there can be dozens or hundreds of 
          //rows for the table, so I don't if adding a listener to each one
          //is the best idea.
          final ObservableList&lt;StringProperty&gt; row = FXCollections.observableArrayList();
          row.add(new SimpleStringProperty("test"));
          row.add(new SimpleStringProperty("one"));
          row.add(new SimpleStringProperty("two"));
  
  
          TableView&lt;ObservableList&lt;StringProperty&gt;&gt; table = new TableView();
          table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
          TableColumn&lt;ObservableList&lt;StringProperty&gt;, String&gt; concatColumns = new TableColumn&lt;&gt;("Concatentated Values");
  
          concatColumns.setCellValueFactory(new Callback&lt;CellDataFeatures&lt;ObservableList&lt;StringProperty&gt;, String&gt;, ObservableValue&lt;String&gt;&gt;() {
              @Override
              public ObservableValue&lt;String&gt; call(CellDataFeatures&lt;ObservableList&lt;StringProperty&gt;, String&gt; p) {
                  ObservableList&lt;StringProperty&gt; row = p.getValue();
  
                  List toConcat = new ArrayList();
                  for (int i = 0; i &lt; row.size(); i++) {
                      toConcat.add(row.get(i));
                      if (i+1 &lt; row.size()) {
                          toConcat.add(", ");
                      }
                  }
                  return Bindings.concat(toConcat.toArray());
              }
          });        
  
          table.getColumns().add(concatColumns);
          table.getItems().add(row);
  
  
          BorderPane root = new BorderPane();        
          HBox buttons = new HBox();        
  
          Button add = new Button();
          add.setText("Add Item");
          add.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
              @Override
              public void handle(ActionEvent event) {
                  row.add(new SimpleStringProperty("added"));
              }
          });
          Button remove = new Button();
          remove.setText("Remove Item");
          remove.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
              @Override
              public void handle(ActionEvent event) {
                  if (row.size() &gt; 0) {
                      row.remove(0);
                  }
              }
          });
          Button change = new Button();
          change.setText("Change Item");
          change.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
              @Override
              public void handle(ActionEvent event) {
                  if (row.size() &gt; 0) {
                      row.get(0).set("Changed");
                  }
              }
          });
          buttons.getChildren().addAll(add, remove, change);
  
          root.setCenter(table);
          root.setBottom(buttons);
  
          Scene scene = new Scene(root, 300, 250);        
          primaryStage.setScene(scene);
          primaryStage.show();
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>
  
  <p>I know "why" it isn't working. The <code>StringExpression</code> is linked to the <code>StringProperty</code> values of the list and not the list itself. Therefore, whenever I add/remove values, it doesn't update. </p>
  
  <p>However, when I remove values (removing the first index), this causes the <code>StringExpression</code> to re-evaluate itself (I guess?), in which case the new added/removed values appear. (Press Remove and then Change)</p>
  
  <p>Simply adding values won't do the trick. (Press Add then Change)</p>
  
  <p>So how, in the cell value factory callback, do I work my code to listen to the <code>ObservableList</code> and return an <code>ObservableValue</code> that can concatenate the list and display when changes occur, including adding/removing?</p>