我有一个包含复杂数据类型列表的对象列表,我需要将这些属性绑定到我的TableView。 我的实体看起来像这样:
public class Customer
{
StringProperty property1;
StringProperty property2;
....
List<Contract> contracts;
}
public class Contract
{
StringProperty property1;
StringProperty property2;
....
}
我的observableArrayList包含一个Customer列表,其中包含一个Contract列表。 获取客户属性很简单:
sampleColumn1.setCellValueFactory(celldata -> celldata.getValue().sampleProperty1());
sampleColumn2.setCellValueFactory(celldata -> celldata.getValue().sampleProperty2());
...
但我无法获得合同清单的属性。 目前我执行以下解决方法:
PropertyValueFactory<Customer, List<Contract>> contractFactory = new PropertyValueFactory<>("contracts");
contractIdColumn.setCellValueFactory(contractFactory);
contractIdColumn.setCellFactory(celldata -> new TableCell<Customer>, List<Contract>>(){
@Override
public void updateItem(List<Contract> contracts, boolean empty){
super.updateItem(contracts, empty);
if(empty)
setText("");
else
setText(contracts.stream().map(Contract::getContractId)
.collect(Collectors.joining("\n")));
}
});
但是这段代码很脏,有人知道用cellValueFactory和lambda表达式做这个的方法吗? 有什么建议吗?
答案 0 :(得分:0)
单元格值工厂只是Callback
获取CellDataFeatures
并返回适当的可观察值,因此您应该可以执行以下操作:
contractIdColumn.setCellValueFactory(cellDataFeatures -> new SimpleStringProperty(cellDataFeatures.getValue().contracts.stream()
.map(Contract::getContractId)
.collect(Collectors.joining("\n"))));
请注意,如果您使用ObservableList
而不是列表,则可以使用Bindings.createStringBinding,以便在列表更新但Customer
元素不会更改时更新值。
答案 1 :(得分:0)
我不认为你的代码太糟糕了。这里重要的是将单元格中显示的数据(由cellValueFactory
提供)与数据的呈现方式(由cellFactory
提供)分开,你有那。数据显然是合同清单,所以你当然想要
TableColumn<Customer, List<Contract>> contractIdColumn ;
并且您需要将单元格值设为ObservableValue<List<Contract>>
,您可以按照以下方式执行此操作:
contractIdColumn.setCellValueFactory(new PropertyValueFactory<>("contracts"));
或者,以类型安全的方式,
contractIdColumn.setCellValueFactory(cellData ->
new SimpleObjectProperty<>(cellData.getValue().getContracts()));
然后,您当前的单元工厂将以文本形式显示合同列表,每个合同ID都在新行上。你可以很容易地修改单元工厂(不改变单元值工厂)来使用,例如ListView<Contract>
:
contractIdColumn.setCellFactory(celldata -> new TableCell<Customer>, List<Contract>>(){
private final ListView<Contract> listView = new ListView<>();
@Override
public void updateItem(List<Contract> contracts, boolean empty){
super.updateItem(contracts, empty);
if(empty)
setGraphic(null);
else {
listView.getItems().setAll(contracts);
setGraphic(listView);
}
}
});
(只是一个粗略的例子;您可能需要设置单元格样式以正确匹配列表视图,并假设Contract
具有适当的toString()
;您可能需要设置单元格工厂ListView
也是,等等。)