How to define which property ListView should use to render
java, javafx, listview
Solution
Use a cell factory.
If the property is immutable, it's pretty straightforward:
ListView<MyDataType> listView = new ListView<>();
listView.setCellFactory(new Callback<ListView<MyDataType>, ListCell<MyDataType>>() {
@Override
public ListCell<MyDataType> call(ListView<MyDataType> lv) {
return new ListCell<MyDataType>() {
@Override
public void updateItem(MyDataType item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
setText(null);
} else {
// assume MyDataType.getSomeProperty() returns a string
setText(item.getSomeProperty());
}
}
};
}
});
If the property can change its value and the list view needs to update dynamically in response to these changes, you need to bind the `textProperty` of the list cell:
listView.setCellFactory(new Callback<ListView<MyDataType>, ListCell<MyDataType>>() {
@Override
public ListCell<MyDataType> call(ListView<MyDataType> lv) {
return new ListCell<MyDataType>() {
@Override
public void updateItem(MyDataType item, boolean empty) {
super.updateItem(item, empty);
textProperty().unbind();
if (item == null) {
setText(null);
} else {
// assumes MyDataType.someProperty() returns a StringProperty:
textProperty.bind(item.someProperty());
}
}
};
}
});
Problem
I have a java bean object list which I would like to display in ListView control. By default ListView uses toString method. How can I define which property to use for rendering in ListView? I want to achieve same functionality as in TableView can be achieved by PropertyValueFactory in this code: ``` @FXML private TableView<Person> mainTableView; //... TableColumn<Person,String> personColumn = new TableColumn<>("Name");List personColumn.setCellValueFactory(new PropertyValueFactory("name")); mainTableView.getColumns().add(personColumn); ``` Edit It looks like there is no easy(out of the box) solution. Based on code from James_D I created generic class to deal with the problem. It wraps PropertyValueFactory - note that PropertyValueFactory firstly looks for method [NAME]Property() trying to get observable, only when it is not found it tries to access standard bean properties. ``` public class PropertyValueFactoryWrapperCellFactory<T> implements Callback<ListView<T>, ListCell<T>> { private final PropertyValueFactory<T, String> pvf; public PropertyValueFactoryWrapperCellFactory(String propertyName) { super(); pvf = new PropertyValueFactory(propertyName); } @Override public ListCell<T> call(ListView<T> param) { return new ListCell<T>() { @Override public void updateItem(T item, boolean empty) { super.updateItem(item, empty); textProperty().unbind(); if (item == null) { return; } TableColumn.CellDataFeatures<T, String> cdf = new TableColumn.CellDataFeatures<>(null, null, item); textProperty().bind(pvf.call(cdf)); } }; } } ``` Usage: ``` @FXML private ListView<Person> mainListView; //... mainListView.setCellFactory(new PropertyValueFactoryWrapperCellFactory("name")); ```