Overview
...
Wiki Markup |
---|
{scrollbar} |
Data Binding and Model-View-Controller Framework
As the XUL framework progressed, Pentaho developed a need for a clean, underlying model-view-controller (MVC) architecture underlying applications has become clearapplication. MVC , or Model-View-Controller, provides for a clean separation between application data (models), view logic (controllers) and the user interface (views). This separation creates loosely coupled components that are easier to maintain and more importantly testabletest. For a more in-depth look at building Pentaho Xul application XUL applications with the MVC pattern, please refer to the excellent article by Aaron Philips: MVC in Pentaho Xul Applications advanced XUL MVC guide.
At the heart of any MVC application framework lies a method for synchronizing data between the models and views. Many frameworks leave this "housekeeping" to the developer. With the introduction of Xul Bindings, we have provided XUL bindings offer a more developer-friendly approach.
What's in a Binding?
A Xul Binding XUL binding object consists of four primary and two optional pieces of data:
- Two XulEventSource objects , – one "Source," the other "Target" – and a property for each to "Bind" together.
- Optionally, A binding strategy (one-way, bi-directional, or bind-once).Optionally,
A
...
converter object to manage data translation between the two is also an option.
Creating a Binding Object
There are several methods provided for creating a binding object in the Xul Framework for creating a Binding ObjectXUL framework. Some are as simple as calling bind() with four Strings strings from an Event Handler. We'll not cover all of those here as they're addressed in detail in MVC in Pentaho Xul Applications. Instead, let's have a look from the ground up.event handler. All of those methods are covered in the aforementioned MVC document. Below is the most basic representation of a binding.:
Code Block |
---|
Binding bind = new BindingDefaultBinding(sourceObject, "firstName", targetObject, "value"); |
When added to a Binding Context binding context (covered explained later in this guide) it will synchronize data between "sourceObject" and "targetObject" by way of "firstName" and "value" respectively.
As Because Java lacks first-class support for Properties and writing Objects properties, and it's bad form to write objects with direct member access is frowned upon, Bindings access , a binding accesses data by way of the Javabean JavaBean standard. A discussion of Javabeans is outside the scope of this article and we will proceed with the assumption that you are familiar with them. At the Javabean JavaBean level our , the binding looks something like this:
No Formatcode |
---|
sourceObject.getFirstName() => targetObject.setValue()
sourceObject.setFirstName() <= targetObject.getValue()
|
Binding Strategies
By default, a binding object represents a synchronization bi-directionally. Any change to the source will update the target and visa-versa. You can optionally prescribe for a one-way binding between source and target as seen belowsuch:
Code Block |
---|
binding.setBindingType(Binding.Type.ONE_WAY);
|
Where ONE_WAY is a type defined in Binding.Type enumeration. A one-way binding will send data from the source to the target but not the other way around.
Future versions will introduce the concept of a "bind-once" strategy that will in essence "flash" a snapshot of data between objects at the time of the binding's instantiation.
Conversions
We You can further extend the flexibility of our your bindings by providing a BindingConvertor object to manage the translation of data between objects. The BindingConvertor class itself is so small worth taking a look at right here.:
BindingConvertor.java
Code Block | ||
---|---|---|
| ||
public abstract class BindingConvertor<V, R> { ... public abstract R sourceToTarget(V value); public abstract V targetToSource(R value); } |
Below is a simple implementation where we bind that binds the value of a XulTextbox with the selectedIndex of a XulMenuList. When the a user enters a numeric string into the text box, it will be converted into an Integer integer before being passed to the setSelectedIndex method of the menu list.:
Code Block |
---|
Binding binding = new BindingDefaultBinding(textbox, "value", dropdown, "selectedIndex"); BindingConvertor conversion = new BindingConvertor<String, Integer>(){ @Override public Integer sourceToTarget(String value) { return Integer.parseInt(value); } @Override public String targetToSource(Integer value) { return value.toString(); } } binding.setConversion(conversion); |
The Binding Context
...
Types of Bindings
So far you have seen DefaultBinding used. This binding is toolkit neutral and all operations done through it happen in the same thread in which the property change event occors. However this can cause problems in both Swt and Swing where UI operations are happening outside of the "event" thread. To correct this you can use SwtBinding or SwingBinding.
However, creating these "flavored" bindings are we call them has the side effect of making your code non-portable. To get around this we have created a BindingFactory for bindings that can be configured outside of your Xul code, Spring injected for instance.
Binding Factories
DefaultBindingFactory (creates the platform neutral bindings)
SwingBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
SwtBindingFactory (forces all events where a XulComponent is the target to happen in the event thread.)
GwtBindingFactory (same as DefautBindingFactory, though compatible with GWT)
Wiki Markup |
---|
{scrollbar} |