1 Reply Latest reply on Nov 5, 2012 4:23 PM by James_D

    bidirectional bind


      how can I bind a detail pane with a selected row in a tableview in both ways?
      Means when I select a row in the tableview the detail fields will updated, also when I Change the value in a detail field the value in the table have to Change.


        • 1. Re: bidirectional bind
          I think you have to use a listener on your selected item property to achieve this (though others may see a more elegant way to do it).

          When I use "editor panels" I like to use separate fxml files and controllers for them, and you can still do this; define a property for your details pane and bind it to the selected item property in the table's selection model. Then register a change listener with the property, and update the bindings in the detail editor's controls to bind bidirectionally to the properties in the selected item.

          Example: first the standard Person class, which all table examples are required to use.

          import javafx.beans.property.SimpleIntegerProperty;
          import javafx.beans.property.SimpleStringProperty;
          import javafx.beans.property.StringProperty;
          import javafx.beans.value.ChangeListener;
          import javafx.beans.value.ObservableValue;
          public class Person {
              private final SimpleIntegerProperty num;
              private final SimpleStringProperty firstName;
              private final SimpleStringProperty lastName;
              public Person(int id, String fName, String lName) {
                this.firstName = new SimpleStringProperty(fName);
                this.lastName = new SimpleStringProperty(lName);
                this.num = new SimpleIntegerProperty(id);
              public StringProperty firstNameProperty() {
                return firstName ;
              public String getFirstName() {
                return firstName.get();
              public void setFirstName(String fName) {
              public StringProperty lastNameProperty() {
                return lastName ;
              public String getLastName() {
                return lastName.get();
              public void setLastName(String fName) {
              public int getId() {
                return num.get();
              public void setId(int id) {
          FXML file for the details pane, which has text fields for first and last name:

          <?xml version="1.0" encoding="UTF-8"?>
          <?import javafx.scene.layout.GridPane?>
          <?import javafx.scene.control.TextField?>
          <?import javafx.scene.control.Label?>
          <GridPane xmlns:fx="http://javafx.com/fxml" fx:controller="DetailsPaneController">
               <Label text="First Name">
               <Label text="Last Name">
               <TextField fx:id="firstNameTextField">
               <TextField fx:id="lastNameTextField">
          Controller for the Details pane: this defines the property for the person being edited, registers a change listener with it, and binds the text fields to the appropriate properties in the Person.

          import javafx.beans.property.ObjectProperty;
          import javafx.beans.property.SimpleObjectProperty;
          import javafx.beans.value.ChangeListener;
          import javafx.beans.value.ObservableValue;
          import javafx.fxml.FXML;
          import javafx.scene.control.TextField;
          public class DetailsPaneController {
            private @FXML TextField firstNameTextField ;
            private @FXML TextField lastNameTextField ;
            private ObjectProperty<Person> personProperty ;
            public void initialize() {
              personProperty = new SimpleObjectProperty<Person>(null) ;
              personProperty.addListener(new ChangeListener<Person>() {
                public void changed(ObservableValue<? extends Person> observable,
                    Person oldValue, Person newValue) {
                  if (oldValue != null) {
                  if (newValue != null) {
            public ObjectProperty<Person> personProperty() {
              return personProperty ;
            public Person getPerson() {
              return personProperty.get();
            public void setPerson(Person p) {
          Main FXML file. Just defines a table view and references the FXML file above.

          <?xml version="1.0" encoding="UTF-8"?>
          <?import javafx.scene.layout.HBox?>
          <?import javafx.scene.control.TableView?>
          <HBox xmlns:fx="http://javafx.com/fxml" fx:controller="TableWithDetailsController">
                    <TableView fx:id="tableView"/>
                    <fx:include source="DetailsPane.fxml" fx:id="detailsPane" />
          And the controller for the main fxml file. The initialize method initializes the table, and binds the selectedItem property to the person property defined in the details pane's controller:

          import javafx.collections.FXCollections;
          import javafx.collections.ObservableList;
          import javafx.fxml.FXML;
          import javafx.scene.control.TableColumn;
          import javafx.scene.control.TableView;
          import javafx.scene.control.cell.PropertyValueFactory;
          public class TableWithDetailsController {
            private @FXML TableView<Person> tableView ;
            private @FXML DetailsPaneController detailsPaneController ;
            public void initialize() {
              final ObservableList<Person> data = FXCollections.observableArrayList(
                  new Person(1, "Joe", "Pesci"),
                  new Person(2, "Audrey", "Hepburn"),
                  new Person(3, "Gregory", "Peck"),
                  new Person(4, "Cary", "Grant"),
                  new Person(5, "Robert", "De Niro")
              TableColumn<Person, Integer> idColumn = new TableColumn<Person, Integer>();
              idColumn.setCellValueFactory(new PropertyValueFactory<Person, Integer>("id"));
              TableColumn<Person, String> firstNameColumn = new TableColumn<Person, String>();
              firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
              TableColumn<Person, String> lastNameColumn = new TableColumn<Person, String>();
              lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
              tableView.getColumns().addAll(idColumn, firstNameColumn, lastNameColumn);
              detailsPaneController.personProperty().bind( tableView.getSelectionModel().selectedItemProperty() );
          Finally, for completeness, the application startup code:

          import javafx.application.Application;
          import javafx.fxml.FXMLLoader;
          import javafx.scene.Parent;
          import javafx.scene.Scene;
          import javafx.stage.Stage;
          public class TableWithDetails extends Application {
            public void start(Stage primaryStage) throws Exception {
              Parent root = FXMLLoader.load(getClass().getResource("TableWithDetails.fxml"));
              Scene scene = new Scene(root);
            public static void main(String[] args) {