2017-01-06 1 views
0

je le code suivant:questions sur DI, ViewModel etc

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() 
      } 
      } 
     } 
     } 
    } 
    } 
} 

J'ai deux questions pour cet exemple:

1) Si je change la valeur et fermer la fenêtre sans engagement (utilisateur peut le faire avec le bouton d'aide [X]) alors seulement ViewModel stockera les changements (et il sera affiché dans l'interface graphique même après la réouverture), mais l'objet POJO du modèle conservera les anciennes données.

Si j'utilisais l'instance de la classe Example (sans DI), alors cette instance recevait tous les changements en même temps.

Par exemple, je ne veux pas de fonctionnalité de validation/annulation, mais je veux une DI et une mise à jour immédiate. Ce que je devrais faire? (Ofcource je peux appeler « commit » pour « événement valeur de changement de textfield »)

2) ViewModel a constructeur avec paramètre et si je tente ExampleView ouvert comme celui-ci

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

alors je suis un RuntimeException évident. Puis-je éviter cela par exemple, par un avertissement de compilateur (ou par quelque chose d'autre)?

Répondre

1

1) Ceci est le comportement par défaut correct de ViewModel. Si vous liez une propriété du modèle de vue à une entrée, les modifications sont immédiatement répercutées dans cette propriété liée, mais seront uniquement vidées dans l'objet de modèle sous-jacent une fois que vous l'avez validée.

Si vous voulez autocommit changements dans les propriétés du modèle de vue arrière dans l'objet modèle sous-jacent, vous pouvez créer la liaison avec l'ensemble de la propriété autocommit true:

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

Vous pouvez également écrire bind(autocommit = true) si cela semble plus clair pour toi. Cela entraînera le retour automatique des modifications dans l'objet sous-jacent. Je souhaite également vous faire savoir qu'en exigeant un élément dans le constructeur de votre modèle de vue, vous empêchez son utilisation avec l'injection, sauf si vous l'utilisez comme setInScope. Cela pourrait convenir à votre cas d'utilisation, mais il vaut la peine de le noter.

2) Le prochain TornadoFX 1.5.10 vous donnera un meilleur message d'erreur runtime si vous oubliez de passer un paramètre. Il introduit également des valeurs par défaut pour les paramètres. Voir https://github.com/edvin/tornadofx/pull/227 pour plus d'informations.