绑定属性不起作用

Bound properties not working

我正在使用 TornadoFX 1.7.5,但我似乎无法使绑定属性起作用。我有以下 ItemViewModels

class DynamicMenuViewModel : ItemViewModel<DynamicMenu>(DynamicMenu()) {
  val title = bind { item?.title?.toProperty() }
  val isBold = bind { item?.isBold?.toProperty() }
  val routes = bind { item?.routes?.toProperty() }
}
data class DynamicMenu(var title: String = "", var isBold: Boolean = false, var routes: MutableList<MenuRouteViewModel> = mutableListOf())

class MenuRouteViewModel : ItemViewModel<MenuRoute>(MenuRoute()) {
  val url = bind { item?.url?.toProperty() }
  val title = bind { item?.title?.toProperty() }
  val isBold = bind { item?.isBold?.toProperty() }
  val showNew = bind { item?.showNew?.toProperty() }
}
data class MenuRoute(var url: String = "", var title: String = "", var showNew: Boolean = false, var isBold: Boolean = false)

绑定如下:

//routesController.dynamicMenu is an instance of DynamicMenuViewModel()

textfield(property = routesController.dynamicMenu.title) {
  prefWidth = formWidth * .5
  gridpaneConstraints {
    columnRowIndex(0, 1)
    marginLeft = 10.0
    columnSpan = 2
    marginBottom = 20.0
  }
}

checkbox(property = routesController.dynamicMenu.isBold){
  gridpaneConstraints {
    columnRowIndex(2, 1)
    marginLeft = 15.0
    marginBottom = 20.0
  }
}

然后,当我单击按钮时,以下函数会提交模型并将它们打印到屏幕上:

  fun onClick(){
    commitModel()
    println(dynamicMenu.item.toString())
    dynamicMenu.item.routes.forEach {
      println(it.item.toString())
    }
  }

  fun commitModel(){
    dynamicMenu.item.routes.forEach {
      it.commit()
    }
    dynamicMenu.commit()
  }

问题是当我 运行 程序编辑文本字段和复选框然后单击 运行s onClick() 按钮时,支持项似乎没有得到更新。因此 none 的更新值被打印到控制台。

我做错了什么?

您可能知道,ViewModel 只能双向绑定到 JavaFX 属性。您的域对象不包含 JavaFX 属性,因此您需要转换它们。但是,您使用的 toProperty() 函数仅对一个值进行操作,并将其转换为 属性。此 属性 无法知道它的字段所有者,因此无法写回域对象。

幸运的是,您可以使用 observable 函数使您的域对象属性也可写:

val url = bind { item?.observable(MenuRoute::url) }

由于 observable 函数在 MenuRoute 对象的特定实例上运行,它现在有足够的信息可以在您 commit() 模型时写回该实例。

如果您考虑将域对象中的属性更改为可观察的,您可以这样写:

val url = bind(MenuRoute::url)

您可以使用 TornadoFX IDEA 插件检查 "Convert all properties to TornadoFX Properties" 自动修改您的属性。这会将您的 MenuRoute 对象转换为:

class MenuRoute {
    val isBoldProperty = SimpleBooleanProperty(false)
    var isBold by isBoldProperty

    val showNewProperty = SimpleBooleanProperty(false)
    var showNew by showNewProperty

    val urlProperty = SimpleStringProperty("")
    var url by urlProperty

    val titleProperty = SimpleStringProperty("")
    var title by titleProperty
}

(您必须手动删除 class 上的 data 修饰符。还要注意当前版本的插件在转换函数中存在一个错误,该错误会保留旧参数 - a新版本即将发布)。

如果您出于各种原因不想这样做,即使对于像您这样的可变变量,我也能够支持这种很好的语法,因此从 TornadoFX 1.7.6 开始,您可以在绑定语句中使用这种语法即使您不想更改数据 classes:

val url = bind(MenuRoute::url)