好的,有两种方法可以做到这一点。首先是实现自己的javafx.utils.ObservableList。 ModifiableObservableListBase 的文档中提供了以下实现(稍作修改):
public class ObservableArrayList<T> extends ModifiableObservableListBase<T> {
private final List<E> delegate = new ArrayList<>();
@Override
public E get(final int index) {
return delegate.get(index);
}
@Override
public int size() {
return delegate.size();
}
@Override
protected void doAdd(final int index, final E element) {
delegate.add(index, element);
}
@Override
protected E doSet(final int index, final E element) {
return delegate.set(index, element);
}
@Override
protected E doRemove(final int index) {
return delegate.remove(index);
}
}
然后,JAXB 可以将此类用作实现列表类型,方法是将以下内容添加到绑定文件中:
<bindings node="//xsd:element[@name='Item']">
<property name="Items" collectionType="myNamespace.ObservableArrayList">
<baseType name="myNamespace.Item" />
</property>
</bindings>
第二个选项,也是我决定使用的选项,是将 JAXB 编组器/解组器配置为使用从生成的类继承的自定义实现类。假设 XSD 定义了一个名为“ItemCollectionType”的复杂类型,其中包含一个名为“Item”的元素定义和无限的maxOccurs。然后我只需将以下内容添加到 JAXB 绑定文件中:
<bindings node="./xsd:complexType[@name='ItemCollectionType']">
<class implClass="myNamespace.ItemCollection" />
</bindings>
<bindings node="//xsd:element[@name='Item']">
<property name="Items">
<baseType name="myNamespace.Item" />
</property>
</bindings>
上面强制在生成的代码中每次出现ItemCollectionType 都用myNamespace.ItemCollection 类型替换。然后,ItemCollectionType 的生成实现包括以下代码:
@XmlElement(name = "Item", required = true, type = myNamespace.Item.class)
protected List<myNamespace.Item> items;
public List<myNamespace.Item> getItems() {
if (items == null) {
items = new ArrayList<myNamespace.Item>();
}
return this.items;
}
然后,我在myNamespace.ItemCollection 中重写了这个方法:
@Override
public ObservableList<Item> getItems() {
if (!(super.getItems() instanceof ObservableList)) {
items = FXCollections.observableList(items);
}
return (ObservableList<Item>)items;
}
当然,这两个选项并不相互排斥。我可以很容易地实现它们,这会将myNamespace.ItemCollection.getItems 的实现简化为一个简单的转换。