I decided to write this question due to missing tutorials and incomplete examples of the following problem. I will be glad if the answer to this question becomes a working example for solving similar problems.
Based on: JavaFX8 list bindings similar to xaml
TASK
Let's make a GUI application using a JavaFX technology (with FXML as a part of this technology for making graphical view) that show collection of users and for every user also his/her collection of cars for example. Let's also use JavaFX properties and bindig mechanisms for synchronize model (data) with GUI.
IMPLEMENTATION
I started with the creation of classes for the user and the car.
User.java
package example;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class User {
public StringProperty firstName;
public StringProperty lastName;
private ObservableList<Car> cars;
public User(String firstName, String lastName, Car[] cars) {
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
this.cars = FXCollections.observableArrayList(cars);
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
public ObservableList<Car> getCars() {
return cars;
}
}
Car.java
package example;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Car {
public StringProperty modelName;
public StringProperty manufacturer;
public Car(String modelName, String manufacturer) {
this.modelName = new SimpleStringProperty(modelName);
this.manufacturer = new SimpleStringProperty(manufacturer);
}
public String getModelName() {
return modelName.get();
}
public StringProperty modelNameProperty() {
return modelName;
}
public void setModelName(String modelName) {
this.modelName.set(modelName);
}
public String getManufacturer() {
return manufacturer.get();
}
public StringProperty manufacturerProperty() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer.set(manufacturer);
}
}
Than I prepare Controller for FXML GUI view with sample collection of users.
Controller.java
package example;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Controller {
private ObservableList<User> users = FXCollections.observableArrayList(
new User("John", "Smith", new Car[] {
new Car("LaFerrari", "Ferrari"),
new Car("FG X Falcon", "Ford")
}),
new User("Ariel", "England", new Car[] {
new Car("ATS", "Cadillac"),
new Car("Camaro", "Chevrolet"),
new Car("458 MM Speciale", "Ferrari")
}),
new User("Owen", "Finley", new Car[] {
new Car("Corsa", "Chevrolet"),
})
);
}
And finally, I also include the generated Main.java.
package example;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Users -- example application");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
QUESTION
The challenge is make FXML GUI view that use JavaFX binding and show prepared collection of users from coresponding Controller. Probably using ListView.
Also I would like specify ListView item design/look in FXML and not in code – because it is part of GUI design. Appropriate JavaFX FXML alternative to .NET XAML ItemTemplate. What about ListCell?
Something in a way of this pseudocode:
users.fxml
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="example.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<ListView items="${users}">
<ListView.ItemTemplate>
<VBox>
<Label Text="${firstName}" />
<Label Text="${lastName}" Style="-fx-background-color: yellow" />
<ListView items="${cars}">
<ListView.ItemTemplate>
<HBox>
<Label Text="${manufacturer}" />
<Label Text=": " />
<Label Text="${modelName}" />
</HBox>
</ListView.ItemTemplate>
</ListView>
</VBox>
</ListView.ItemTemplate>
</ListView>
</GridPane>