MVC中的模型可以回滚到上一个有效状态吗?

时间:2018-11-27 11:02:38

标签: kotlin tornadofx

我从这里开始遵循TornadoFX指南,试图运行示例向导: Wizard

我遇到以下麻烦,请参阅第3项):

1)当我按Cancel时,这些值将回滚到   下次打开

2)当我按Finish时,下次打开时这些值仍在向导中

3)当我现在按Cancel时,更改不会回滚到2),而是   1),我。 e。空字段

我如何获得不同的Cancel行为:将CustomerModel回退到最后一个有效状态?

这是我更新的CustomerWizard.kt

package com.example.demo.view

import com.example.demo.app.Customer
import com.example.demo.app.CustomerModel
import tornadofx.*
class CustomerWizard : Wizard("Create customer", "Provide customer information") {
    val customer: CustomerModel by inject()

    override val canGoNext = currentPageComplete
    override val canFinish = allPagesComplete

    override fun onCancel() {
        super.onCancel()
        customer.rollback()

    }

    override fun onSave() {
        super.onSave()
        customer.commit()

        println("customer.name=" + customer.name)
        println("customer.type=" + customer.type)
        println("customer.zip=" + customer.zip)
        println("customer.city=" + customer.city)
    }

    init {
        graphic = resources.imageview("/graphics/customer.png")
        add(BasicData::class)
        add(AddressInput::class)
    }
}

class BasicData : View("Basic Data") {
    val customer: CustomerModel by inject()

    override val complete = customer.valid(customer.name)

    override val root = form {
        fieldset(title) {
            field("Type") {
                combobox(customer.type, Customer.Type.values().toList())
            }
            field("Name") {
                textfield(customer.name).required()
            }
        }
    }
}

class AddressInput : View("Address") {
    val customer: CustomerModel by inject()

    override val complete = customer.valid(customer.zip, customer.city)

    override val root = form {
        fieldset(title) {
            field("Zip/City") {
                textfield(customer.zip) {
                    prefColumnCount = 5
                    required()
                }
                textfield(customer.city).required()
            }
        }
    }
}

这是我的CustomerModel.kt

package com.example.demo.app

import tornadofx.*

class CustomerModel(customer: Customer? = null) : ItemViewModel<Customer>(customer) {
    val name = bind(Customer::nameProperty, autocommit = true)
    val zip  = bind(Customer::zipProperty, autocommit = true)
    val city = bind(Customer::cityProperty, autocommit = true)
    val type = bind(Customer::typeProperty, autocommit = true)
}

这是我的MainView.kt

package com.example.demo.view

import com.example.demo.app.Customer
import com.example.demo.app.CustomerModel
import com.example.demo.app.Styles
import javafx.geometry.Pos
import javafx.scene.layout.Priority
import javafx.scene.paint.Color
import tornadofx.*

class MainView : View("Hello TornadoFX") {

    private val myCustomer: Customer? = Customer("test", 12345, "", Customer.Type.Private)
    override val root = drawer {
            item("Generate & sign", expanded = true) {
                button("Add Customer").action {
                    find<CustomerWizard>(Scope(CustomerModel(myCustomer))).openModal()
                }
            }
            item("Verify") {
                borderpane {
                    top = label("TOP") {
                        useMaxWidth = true
                        alignment = Pos.CENTER
                        style {
                            backgroundColor += Color.RED
                        }
                    }

                    bottom = label("BOTTOM") {
                        useMaxWidth = true
                        alignment = Pos.CENTER
                        style {
                            backgroundColor += Color.BLUE
                        }
                    }

                    left = label("LEFT") {
                        useMaxWidth = true
                        useMaxHeight = true
                        style {
                            backgroundColor += Color.GREEN
                        }
                    }

                    right = label("RIGHT") {
                        useMaxWidth = true
                        useMaxHeight = true
                        style {
                            backgroundColor += Color.PURPLE
                        }
                    }

                    center = label("CENTER") {
                        useMaxWidth = true
                        useMaxHeight = true
                        alignment = Pos.CENTER

                        style {
                            backgroundColor += Color.YELLOW
                        }
                    }
                }
            }
            item("Sign next") {
                borderpane {
                    top = label("TOP") {
                        useMaxWidth = true
                        alignment = Pos.CENTER
                        style {
                            backgroundColor += Color.RED
                        }
                    }

                    bottom = label("BOTTOM") {
                        useMaxWidth = true
                        alignment = Pos.CENTER
                        style {
                            backgroundColor += Color.BLUE
                        }
                    }

                    left = label("LEFT") {
                        useMaxWidth = true
                        useMaxHeight = true
                        style {
                            backgroundColor += Color.GREEN
                        }
                    }

                    right = label("RIGHT") {
                        useMaxWidth = true
                        useMaxHeight = true
                        style {
                            backgroundColor += Color.PURPLE
                        }
                    }

                    center = label("CENTER") {
                        useMaxWidth = true
                        useMaxHeight = true
                        alignment = Pos.CENTER

                        style {
                            backgroundColor += Color.YELLOW
                        }
                    }
                }
            }
        }

        //class Link(val name: String, val uri: String)
        //class Person(val name: String, val nick: String)

        // Sample data variables left out (iPhoneUserAgent, TornadoFXScreencastsURI, people and links)
    }

1 个答案:

答案 0 :(得分:2)

rollback()上调用ItemViewModel时,它将回滚到基础item中找到的数据;如果您从未使用过{一个项目。

在您的情况下,这意味着您需要为ItemViewModel的{​​{1}}属性分配Customer。完成此操作后,可以调用itemCustomerModel会显示rollback()所支持的状态。

如果重新打开向导时得到的状态相同,则意味着您已经重新打开了完全相同的向导实例。向导扩展了CustomerModel,使其在其作用域内成为一个单例,因此,如果您仅调用Customer来定位向导而不指定范围,则第二次尝试将获得与第一个相同的实例。

您没有发布向导的初始化代码,但是如果要避免这种情况,通常应该为向导创建一个新的作用域。如果要向导编辑特定的客户实例,则应该执行以下操作:

View

因此,让视图模型在构造函数中接受实例是正常的,然后将该实例传递给find()构造函数,以便自动为您分配项目:

val model = CustomermerModel()
model.item = myCustomer
find<CustomerWizard>(Scope(model).openModal()

并不是我确定要为CustomerModel允许使用无参数的构造函数,以在范围内没有CustomerModel的情况下支持注入。在这种情况下,将创建一个新的CustomerModel(不支持任何客户项目),因此这种情况需要一个无参数的构造函数。

安装该命令后,向导初始化代码将变为:

ItemViewModel

希望这会有所帮助。