2017-07-24 52 views
0

考虑如下因素例如:TornadoFX如何添加验证,而编辑的TableView

class Item(name: String, number: Int) { 
    val nameProperty = SimpleStringProperty(name) 
    var name by nameProperty 

    val numberProperty by lazy { SimpleIntegerProperty(number) } 
    var number by 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).makeEditable(NumberStringConverter()) 
      enableCellEditing() 
     } 
    } 
} 

我如何添加一个validator在编辑细胞?要做到这一点的唯一方法是添加rowExpander与一些textfield并尝试在那里验证模型?

回答

0

您可以实现自己的cellfactory并返回一个单元格,该单元格在编辑模式下显示与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 Solution

虽然它起作用,但由于节点经常重新创建,所以很浪费。如果性能是一个问题,我会推荐第一种方法,直到我们像ListView那样得到支持TableView的cellFragment

编辑:我实现了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开始。

+0

我用更强大的解决方案更新了答案,使用了TornadoFX 1.7.9中引入的TableCellFragment :) –

+0

哇,谢谢Edvin,看起来对我的情况非常好 – sk1ey

+0

太棒了!你可以通过使用快照编译已经检查出来:) –