Может ли модель в MVC откатиться до последнего действительного состояния? - PullRequest
0 голосов
/ 27 ноября 2018

Отсюда я следую Руководству по TornadoFX, пытаясь запустить пример мастера: Wizard

У меня возникли следующие проблемы, см. Пункт 3):

1) Когда я нажимаю Cancel значения возвращаются к пустым значениям при следующем открытии

2) Когда я нажимаю Finish, значения остаются в мастере при следующем открытии

3)Когда я теперь нажимаю Cancel изменения не возвращаются к 2), а к 1), то есть к пустым полям

Как мне получить другое поведение 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 голосов
/ 27 ноября 2018

Когда вы вызываете rollback() для ItemViewModel, он откатится к данным, найденным в базовом item, или к пустым значениям, если вы никогда не поддерживали свой ItemViewModel с элементом.

В вашем случае это означает, что вам необходимо присвоить Customer свойству item вашего CustomerModel.После того, как вы это сделаете, вы можете позвонить rollback(), и CustomerModel покажет состояние из Customer, которое он поддерживает.

Если вы получите то же состояние при повторном открытии мастера, это означает, чточто вы снова открыли тот же экземпляр мастера.Мастер расширяет View, что делает его одиночным в пределах его области, поэтому, если вы просто вызовете find(), чтобы найти мастера без указания области, вторая попытка даст вам тот же экземпляр, что и первая.

Вы не опубликовали свой код инициализации Мастера, но обычно вам следует создать новую область действия для Мастера, если вы хотите избежать этого.Если вы хотите, чтобы мастер отредактировал конкретный экземпляр клиента, вы должны сделать:

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

По этой причине нормально позволить модели представления принимать экземпляр в конструкторе, который вы передаете *Конструктор 1022 *, так что элемент назначается автоматически:

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

Не то чтобы я разрешил использовать конструктор без аргументов для CustomerModel, чтобы поддерживать инъекцию в тех случаях, когда в CustomerModel нетсфера уже.В этом случае будет создан новый CustomerModel (не поддерживающий элемент клиента), поэтому в этой ситуации требуется конструктор без аргументов.

После этого код инициализации мастера становится:

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...