Skip to content
Manuel Mauky edited this page Mar 22, 2016 · 20 revisions

This feature is currently beta and will be part of version 1.5.0.

What are Scopes in mvvmFX?

A Scope in mvvmFX is a data context between ViewModels. They are used to decouple dependant ViewModels from each other.

Types of Scopes

There are two types of Scopes:

  • Global scopes which are Singletons, which can be used with the @InjectViewModel Annotation
  • Scopes that are related to an ID

###API - Use @Inject or the ScopeStore

public class TestScope implements Scope {
    private StringProperty myScopeString = new SimpleStringProperty();
    private BooleanProperty myScopeBoolean = new SimpleBooleanProperty();

    public StringProperty myScopeStringProperty() {
        return myScopeString;
    }

    public BooleanProperty myScopeBooleanProperty() {
        return myScopeBoolean;
    }
}
public class SomeViewModel1 implements ViewModel {

    //Global Instance of the Scope-type will be injected 
    //-> it doesn't matter in which ViewModel you do this -> you'll get the same instance	
    @InjectScope
    private TestScope scope1;

    //gets a scope for this ID. If it already exists in the storage you get it,
    @InjectScope("coolId2")
    private TestScope scope2;

    SomeViewModel1 (){
        scope1.myScopeStringProperty().addListener(b,oldValue,newValue)->System.out.println(newValue));
        scope2.myScopeBooleanProperty().addListener(b,oldValue,newValue)->System.out.println(newValue));
    }
}
public class SomeViewModel2 implements ViewModel {
    private TestScope scope1;
    private TestScope scope2;

    SomeViewModel2 (){
        //Global Instance of the Scope-type will returned 
        scope1 = ScopeStorage.get(TestScope.class);

        //returns the scope for this ID
        scope2 = ScopeStorage.get(TestScope.class, "cooldId2");
		
        //The property changes will cause a Syso in SomeViewModel1
        scope1.myScopeStringProperty().set("Communicate to other ViewModels");
        scope2.myScopeBooleanProperty().set(true); 
    }
}

#Examples

A good example are Master/Detail Views where you have ViewModels for Master and Detail. In this case you have to transport the information of the current selection from the Master-ViewModel to the Detail-ViewModel.

public class PersonMasterDetailScope implements Scope {

    public ObjectProperty<Person> displayedPerson = new SimpleObjectProperty<>();
    //Some logic which sets the displayed person - for example when the user chooses an element in the master list
    ...
}
public class PersonMasterViewModel implements ViewModel {
	
    @InjectScope
    private TestScope scope;

    ObjectProperty<Person> selectedPerson = new SimpleObjectProperty<>();

    public PersonMasterViewModel () {
        ...
        scope.displayedPerson.bind(selectedPerson);
        ...
    }	
}
public class PersonDetailViewModel implements ViewModel {
	
    @InjectScope
    private TestScope scope;

    public PersonDetailViewModel () {      
        scope.displayedPerson.addListener((b,o,newSelectedPerson)->initViewModelWithPerson(newSelectedPerson));
    }	
}