代码之家  ›  专栏  ›  技术社区  ›  Leder

MVC中的模型能否回滚到上一个有效状态?

  •  0
  • Leder  · 技术社区  · 7 年前

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

    Cancel 这些值将在上回滚为空值 下次开放

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

    3) 当我现在按下 取消 更改不会回滚到2),而是回滚到 1) ,i。E空旷的田野

    我怎样才能与众不同 行为:将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 回复  |  直到 7 年前
        1
  •  2
  •   Edvin Syse    7 年前

    当你打电话的时候 rollback() ItemViewModel item ,或如果您从未支持 ItemViewModel 带着一件物品。

    Customer 你的财产 CustomerModel 回滚() 将从中显示状态

    如果在重新打开向导时获得相同的状态,则表示您已重新打开完全相同的向导实例。向导将扩展 View ,这使它成为其范围内的单例,因此如果您只需调用 find() 要定位向导而不指定作用域,第二次尝试将获得与第一次相同的实例。

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

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

    出于这个原因,让视图模型接受构造函数中的实例是正常的,您可以将该实例传递给 ItemViewModel 构造函数,以便自动为您分配项:

    class CustomerModel(customer: Customer? = null) : ItemViewModel<Customer>(customer)
    

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

    find<CustomerWizard>(Scope(CustomerModel(myCustomer)).openModal()
    

    希望这有帮助。