I was wondering how to bind values where the binding source can be null.
I have a property:
private ObjectProperty<Operation> operation = new SimpleObjectProperty<>(null);
I also have a text box:
@FXML private Text txtCurrentOperation;
I would like to bind textProperty fields to the value of the work object.
My first thought was to use FluentAPI with its if / then / construct otherwise, but it is readily evaluated so that the solution is:
Bindings.when(operation.isNotNull()) .then("null") .otherwise(operation.get().getName()));
will cause NPE, because the otherwise parameter is evaluated regardless of the result of when .
My next idea was to use lambda somehow:
txtCurrentOperation.textProperty().bind(() -> new SimpleStringProperty( operation.isNotNull().get() ? "Null" : operation.get().getName() ));
But the binding does not have the solution allowed by the lambda. (Later, I realized that this cannot be, because the real work goes backward: changing a related object (operation) will lead to updating the binder (a property of the field text).)
In some articles, I suggested using an “extreme” value for a property instead of null. But the operation is a complex and heavy component, so it’s easy to build an artificial instance to represent null. Moreover, it seems to me boilercode that the binding mechanism is designed to help eliminate.
My next attempt was to logically change the direction of the binding and add a listener to the property of the operation and allow it to update the field programmatically. It works and is quite simple, while the need for updating depends only on instances of the operation object:
operation.addListener((e) -> { txtCurrentOperation.setText(operation.isNull().get() ? "Null" : operation.get().getName()); }); operation.set(oper);
It is relatively simple, but it doesn’t work: it throws out “The bound value cannot be set”. an exception, and I don’t understand why the text property of the control is considered bound.
I'm out of ideas. After a long search, I still can not solve a simple problem to update the text field in different ways depending on whether the source is zero or not.
It seems such a simple and everyday problem that I'm sure I missed this solution.