Вы можете реализовать свою собственную фабрику ячеек и вернуть ячейку, которая показывает текстовое поле, привязанное к ViewModel, в режиме редактирования и метку, если нет. В качестве альтернативы, если вас устраивает всегда отображать текстовое поле, вы можете использовать cellFormat
и привязать текущий элемент к ItemModel, чтобы вы могли прикрепить проверку:
class ItemModel(item: Item) : ItemViewModel<Item>(item) {
val name = bind(Item::nameProperty)
val number = bind(Item::numberProperty)
}
class MainView : View("Example") {
val items = listOf(Item("One", 1), Item("Two", 2)).observable()
override val root = vbox {
tableview(items) {
column("Name", Item::nameProperty).makeEditable()
column("Number", Item::numberProperty).cellFormat {
val model = ItemModel(rowItem)
graphic = textfield(model.number, NumberStringConverter()) {
validator {
if (model.number.value == 123) error("Invalid number") else null
}
}
}
}
}
}
Это будет выглядеть так:
![Решение CellFormat](https://i.stack.imgur.com/pqzso.png)
Хотя это работает, это довольно расточительно, поскольку узлы часто воссоздаются. Я бы рекомендовал подход номер один, если производительность вызывает беспокойство, пока мы не получим cellFragment
поддержку TableView, как у нас есть для ListView.
РЕДАКТИРОВАТЬ: я реализовал поддержку cellFragment
, поэтому можно создать более надежное решение, которое будет отображать метку, когда не находится в режиме редактирования, и проверяющее текстовое поле, когда вы входите в режим редактирования.
class ItemModel : ItemViewModel<Item>() {
val name = bind(Item::nameProperty)
val number = bind(Item::numberProperty)
}
class MainView : View("Example") {
val items = listOf(Item("One", 1), Item("Two", 2)).observable()
override val root = vbox {
tableview(items) {
column("Name", Item::nameProperty).makeEditable()
column("Number", Item::numberProperty).cellFragment(NumberEditor::class)
}
}
}
class NumberEditor : TableCellFragment<Item, Number>() {
// Bind our ItemModel to the rowItemProperty, which points to the current Item
val model = ItemModel().bindToRowItem(this)
override val root = stackpane {
textfield(model.number, NumberStringConverter()) {
removeWhen(editingProperty.not())
validator {
if (model.number.value == 123L) error("Invalid number") else null
}
// Call cell.commitEdit() only if validation passes
action {
if (model.commit()) {
cell?.commitEdit(model.number.value)
}
}
}
// Label is visible when not in edit mode, and always shows committed value (itemProperty)
label(itemProperty) {
removeWhen(editingProperty)
}
}
// Make sure we rollback our model to avoid showing the last failed edit
override fun startEdit() {
model.rollback()
}
}
Это будет возможно начиная с TornadoFX 1.7.9.
person
Edvin Syse
schedule
24.07.2017