0

我有以下代码:

class ExampleView :View("My Example view") {
  val model:ExampleModel by inject()

  override val root= vbox {
    textfield(model.data)
    button("Commit") {
      setOnAction {
        model.commit()
        closeModal()
      }
    }
    button("Rollback") {
      setOnAction {
        model.rollback()
        closeModal()
      }
    }
    button("Just quit") {
      setOnAction {
        closeModal()
      }
    }
  }

}

class Example() {
  var data by property<String>()
  fun dataProperty() = getProperty(Example::data)
}

class ExampleModel(example: Example) : ItemViewModel<Example>() {
  init {
    item = example
  }
  val data = bind { item?.dataProperty() }
}

class MainView : View() {
  val example:Example
  override val root = BorderPane() 

  init {
    example = Example()
    example.data = "Data for example"
    val exampleModel = ExampleModel(example)
    with(root){
      top {
        menubar {
          menu("Test") {
            menuitem("Example - 1") {
              val scope = Scope()
              setInScope(exampleModel, scope)
              find<ExampleView>(scope).openWindow()
            }
            menuitem("Example - 2") {
              val scope = Scope()
              setInScope(exampleModel, scope)
              find<ExampleView>(scope).openWindow()
            }
          }
        }
      }
    }
  }
}

对于这个例子,我有两个问题:

1)如果我更改值并在没有提交的情况下关闭窗口(用户可以使用帮助 [X] 按钮执行此操作),那么只有 ViewModel 会存储更改(即使在重新打开后它也会显示在 GUI 中),但模型POJO 对象将保留旧数据。

如果我使用 Example 类的实例(没有 DI),那么这个实例会立即收到所有更改。

例如,我不想要提交/回滚功能,但我想要 DI 和立即更新。我该做什么?(我可以为“文本字段更改值事件”调用“提交”)

2) ViewModel 具有带参数的构造函数,如果我尝试像这样打开 ExampleView

find<ExampleView>(Scope()).openWindow()

然后我得到了一个明显的 RuntimeException。例如,我可以通过编译器警告(或其他方式)来避免这种情况吗?

4

1 回答 1

2

1) 这是 ViewModel 的正确默认行为。如果您将视图模型的属性绑定到输入,则更改会立即反映在该绑定属性中,但只有在您提交后才会刷新到底层模型对象中。

如果您想将视图模型属性中的更改自动提交回底层模型对象,您可以创建将autocommit属性设置为 true 的绑定:

val data = bind(true) { item?.dataProperty() }

bind(autocommit = true)如果你觉得更清楚,你也可以写。这将导致任何更改自动刷新回底层对象。

我还想让您知道,通过在视图模型的构造函数中需要一个项目,您可以有效地防止它与注入一起使用,除非您像使用setInScope. 这可能适合您的用例,但值得注意。

2)如果您忘记传递参数,即将推出的 TornadoFX 1.5.10 将为您提供更好的运行时错误消息。它还引入了参数的默认值。有关更多信息,请参阅https://github.com/edvin/tornadofx/pull/227

于 2017-01-07T11:08:13.187 回答