Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connecting two view models to a single view #610

Open
chuuck opened this issue May 9, 2020 · 5 comments
Open

Connecting two view models to a single view #610

chuuck opened this issue May 9, 2020 · 5 comments

Comments

@chuuck
Copy link

chuuck commented May 9, 2020

I am trying to find a way to bind two view models to a single view, however, I cannot find a way to achieve my goal.

@manuel-mauky
Copy link
Collaborator

This is not possible. A single ViewModel can be used by multiple Views but each View can only have a single ViewModel.
The idea is that from the perspective of the View it shouldn't matter how the ViewModel is implemented.
But you can inject other ViewModels into the one ViewModel of the View and pass properties through the main ViewModel so that indirectly the View is working together with multiple ViewModels. This is then an implementation detail of the ViewModel which is OK.

@lqyaos
Copy link

lqyaos commented Dec 21, 2021

But you can inject other ViewModels into the one ViewModel of the View and pass properties through the main ViewModel so that indirectly the View is working together with multiple ViewModels.

How can I achieve this elegantly? The problem I have now is: I have a lot of functions in a single interface, and I can't write them all on the same viewmodel. I need a form similar to fragments.

@manuel-mauky
Copy link
Collaborator

The injection itself isn't depending on mvvmFX but depends on your dependency-injection framework.

I'm not sure what you mean with "fragments". I have the feeling that your issues are not a mvvmfx issue but a more general software architecture/design issue. Having lots of functions in a single interface might be not a good idea (possibly a violation of interface segregation principle).

The best way that OOP provides is composition: Implement the functions that belong to each other in one or multiple classes, create/inject instances of these classes in your ViewModel to use the functions. But the actual design highly depends on your specific use-case.

@lqyaos
Copy link

lqyaos commented Dec 22, 2021

Sorry, I may not express it clearly. What I mean is that I want a view to be divided into multiple fragments, and then there are multiple viewmodels to manage each fragment, that is, one view corresponds to multiple viewmodels.

@manuel-mauky
Copy link
Collaborator

Ok, I understand. This is possible with mvvmFX the way I explained above. In mvvmFX, normally there is a one-to-one connection between View and ViewModels. This is the usual case but it's also possible to have one ViewModel which is used by multiple Views.
What is not possible is to have One View to use multiple ViewModels.
One View always knows exactly one ViewModel. However, the way this ViewModel works internally is hidden from the View. The ViewModel itself internally can use whatever other classes, services or other ViewModels without the View even knowing. It's an implementation detail and this kind of architecture gives you the freedom to refactor the ViewModel without having to change anything in the View.
For example, immagine you start with a big ViewModel with lots of exposed properties which are bound by the View. Later on you deside to refactor this by extracting parts of the logic and properties to other classes (name them ViewModel or whatever).
You change the implementation of your ViewModel without changing it's API and it's observable behavior.

A small example:

// before

class MyViewModel implements ViewModel {
     private StringProperty firstname = new SimpleStringProperty();

     private StringProperty lastname = new SimpleStringProperty();


     public StringProperty firstnameProperty() {
        return firstname;
     }

     public StringProperty lastnameProperty() {
        return lastname;
     }
}

// after

class MyViewModel implements ViewModel {
     private PersonViewModel personVM = // ...

     public StringProperty firstnameProperty() {
        return personVM.firstnameProperty();
     }

     public StringProperty lastnameProperty() {
        return personVM.lastnameProperty();
     }
}

This way you can re-use the "PersonViewModel" in the example.

The intersting point is, how you get the instance of the other viewModel. This is were dependency injection comes into play but this is beyond mvvmFX. mvvmFX doesn't provide general DI but only for objects managed by the framework itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants