Is it possible to associate the non-empty state of an ObservableList inside ObjectProperty with the Bindings API?

I have a situation where I want to bind BooleanProperty to a BooleanProperty ObservableList state wrapped inside ObjectProperty .

Here is a basic overview of the behavior I'm looking for:

  ObjectProperty<ObservableList<String>> obp = new SimpleObjectProperty<ObservableList<String>>(); BooleanProperty hasStuff = new SimpleBooleanProperty(); hasStuff.bind(/* What goes here?? */); // ObservableProperty has null value assertFalse(hasStuff.getValue()); obp.set(FXCollections.<String>observableArrayList()); // ObservableProperty is no longer null, but the list has not contents. assertFalse(hasStuff.getValue()); obp.get().add("Thing"); // List now has something in it, so hasStuff should be true assertTrue(hasStuff.getValue()); obp.get().clear(); // List is now empty. assertFalse(hasStuff.getValue()); 

I would like to use builders in the Bindings class instead of embedding a custom binding chain.

The Bindings.select(...) method theoretically does what I want, except that there is no Bindings.selectObservableCollection(...) and discarding the return value from the general select(...) and passing it to Bindings.isEmpty(...) does not work. That is the result:

  hasStuff.bind(Bindings.isEmpty((ObservableList<String>) Bindings.select(obp, "value"))); 

throws a ClassCastException :

 java.lang.ClassCastException: com.sun.javafx.binding.SelectBinding$AsObject cannot be cast to javafx.collections.ObservableList 

Is it possible to use this use case only using the Bindings API?


Decision

Based on the answer from @fabian, here is the solution that worked:

  ObjectProperty<ObservableList<String>> obp = new SimpleObjectProperty<ObservableList<String>>(); ListProperty<String> lstProp = new SimpleListProperty<>(); lstProp.bind(obp); BooleanProperty hasStuff = new SimpleBooleanProperty(); hasStuff.bind(not(lstProp.emptyProperty())); assertFalse(hasStuff.getValue()); obp.set(FXCollections.<String>observableArrayList()); assertFalse(hasStuff.getValue()); obp.get().add("Thing"); assertTrue(hasStuff.getValue()); obp.get().clear(); assertFalse(hasStuff.getValue()); 
+8
java javafx javafx-2 binding observable
source share
3 answers

I see no way to do this using only the Bindings API. ObservableList has no empty property, so you cannot use

 Bindings.select(obp, "empty").isEqualTo(true) 

and

 ObjectBinding<ObservableList<String>> lstBinding = Bindings.select(obp); hasStuff.bind(lstBinding.isNotNull().and(lstBinding.isNotEqualTo(Collections.EMPTY_LIST))); 

does not work, because it is updated only when the list changes, but not when the contents change (i.e., the third statement fails).

But the custom snap chain you have to create is very simple:

 SimpleListProperty lstProp = new SimpleListProperty(); lstProp.bind(obp); hasStuff.bind(lstProp.emptyProperty()); 
+5
source share

This can be done with fewer variables:

 SimpleListProperty<String> listProperty = new SimpleListProperty<>(myObservableList); BooleanProperty hasStuff = new SimpleBooleanProperty(); hasStuff.bind(not(listProperty.emptyProperty())); 
+1
source share

Should it really be ObjectProperty<ObservableList<String>> ? If so, this answer does not solve your problem ...

But I think that if you change the obp type as follows:

 Property<ObservableList<String>> obp = new SimpleListProperty<>(); 

You should be able to use:

 hasStuff.bind(Bindings.isEmpty((ListProperty<String>) obp)); 
0
source share

All Articles