Evaluation context

By default, expressions are evaluated against the root element of the FXML document. This can be used to bind properties of controls to custom properties defined in the code-behind class. For other use cases, alternative evaluation contexts can be specified:

Selector Evaluates against
(no notation) root element, or fx:context if set
self current element
parent parent of the current element, equivalent to parent[0]
parent[N] N-th ancestor of the current element
parent<MyType> first MyType ancestor of the current element
parent<MyType>[N] N-th MyType ancestor of the current element

Context selectors are specified as part of the expression path, separated by a forward slash:

<Rectangle height="${self/width}"/>

Using fx:Evaluate with self or parent selectors may lead to unexpected results, since the evaluated value may depend on the order of element initialization.

Consider the following example:

<Pane prefWidth="123">
    <Label prefWidth="$parent/prefWidth"/>
</Pane>

Perhaps surprisingly, Label.prefWidth will be -1.0 instead of 123.0. The reason for this behavior is that child elements are initialized before parent elements, which means that when the fx:Evaluate expression is evaluated, Pane.prefWidth still has its default value of -1.0.

In cases like these, an observable binding expression should be preferred.

Changing the default evaluation context with fx:context

The default evaluation context is the root element of the FXML document. This can be changed with the fx:context attribute, which can be bound to an arbitrary object:

com/sample/MyControl.java
public class MyControl extends MyControlBase {
    final MyBindingContext myContext;

    MyControl() {
        myContext = new MyBindingContext();
        initializeComponent();
    }
}

class MyBindingContext {
    ObjectProperty<User> userProperty();
}
com/sample/MyControl.fxml
<StackPane xmlns="http://javafx.com/javafx" xmlns:fx="http://jfxcore.org/fxml/2.0"
           fx:subclass="com.sample.MyControl"
           fx:context="$myContext">
    <!-- "user.name" will be evaluated against "myContext" -->
    <Label text="${user.name}"/>
</StackPane>

fx:context can be set not only to a specific object, but also be bound to an ObservableValue if the evaluation context is expected to change. Note that this will incur listener management overhead.


This site uses Just the Docs, a documentation theme for Jekyll.