有关DI,ViewModel等的问题

我有以下代码:

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和立即更新。 我该做什么? (我可以为“textfield change value event”调用“commit”)

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

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

那么我得到了一个明显的RuntimeException。 我是否可以通过编译器警告(或其他方式)来避免这种情况?

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

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

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

如果看起来更清楚,你也可以写bind(autocommit = true) 。 这将导致任何更改被自动刷新到底层对象中。

我也想让你知道,通过在你的视图模型的构造函数中要求一个项目,你可以有效地防止它被注入使用,除非你像使用setInScope一样使用setInScope 。 这可能对您的使用情况很好,但值得注意。

2)如果你忘记传递一个参数,即将到来的TornadoFX 1.5.10会给你一个更好的运行时错误信息。 它还引入了参数的默认值。 有关更多信息,请参见https://github.com/edvin/tornadofx/pull/227