Jump to: navigation, search

JFace Data Binding/Tutorial

Data Binding Tutorial

--Frank.schaare.gmail.com 20:24, 12 October 2007 (EDT)

Terms


  • Model: a Model represents the Domain Model of your Application.
  • Target: a Target represents the GUI side.

A first simple binding


Looking at the example snippets, you'll see a few SWT examples. This time, we'll create a very simple RCP view. Our createPartControl method has just one Text Element:

	public void createPartControl(Composite parent){

	name = new Text(parent, SWT.BORDER);
	final GridData gd_name = new GridData(SWT.FILL, SWT.CENTER, true, false);
	name.setLayoutData(gd_name);

	}

That Text name represents the Target of our binding. Let's add a simple Model:

	static class Person extends ModelObject{
		// A property...
		String name = "HelloWorld";

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
	}

As you may have noticed, the Person Class extends Model Object. If you want to bind your Domain Models, you'll have to ensure support for PropertyChangeSupport. The easiest way to achieve this, is to extend Model Object. You'll find a suitable Template in org.eclipse.jface.examples.databinding package.

To create your first binding, you need to instantiate a DataBindingContext. Create a method like this:

	private DataBindingContext initDataBindings() {
	DataBindingContext bindingContext = new DataBindingContext();

	return bindingContext;
	}

Next, we add a IObservableValue Object for the Target:

	private DataBindingContext initDataBindings() {
	DataBindingContext bindingContext = new DataBindingContext();

        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);

	return bindingContext;
	}

The observeText method takes two params

  • name: the observed Control
  • event: when the model will be updated. Choices are SWT.FocusOut, SWT.Modify or SWT.NONE

Second, we add a IObservableValue Object for the Model:

	private DataBindingContext initDataBindings() {
	DataBindingContext bindingContext = new DataBindingContext();
        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);

	IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");

	return bindingContext;
	}

The observeValue method takes two params

  • bean: the observed bean
  • propertyName: the name of the observed property, in our case the persons name.

Last, we need to bind Target and Model. This is done through the DataBindingContext#bindValue method:

	private DataBindingContext initDataBindings() {
	DataBindingContext bindingContext = new DataBindingContext();
        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
	IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");

	bindingContext.bindValue(nameTextObserveWidget, personNameObserveValue, null, null);

	return bindingContext;
	}

The bindValue method takes four params

  • targetObservableValue: our first created IObservableValue
  • modelObservableValue: our second created IObservableValue
  • UpdateValueStrategy targetToModel: will be dicusssed later
  • UpdateValueStrategy modelToTarget: will be dicusssed later

That's it. You successfully created your first JFace Data Binding !

Introducing UpdateValueStrategy


Next, we'll take a closer look at Snippet014WizardDialog, to explore some advanced features.

Snippet014WizardDialog includes an inner class SampleWizardModel:

	static class SampleWizardModel {
		IObservableValue intValue = new WritableValue(null, Integer.class);
		IObservableValue dateValue = new WritableValue(null, Date.class);
	}

Again, you'll find an IObservableValue, but with a few differences to our first example. First, it is instantiated as a WritableValue(Object initialValue, Object valueType). This is a mutable implementation of IObservableValue that will maintain a value and fire change events when the value changes. Second, the IObservableValue is instantiated inside the Model, differently from our first example. If you are in a situation where you can't get PropertyChangeSupport by extending a class similar to ModelObject, this variant may be a good alternative.

As another nested inner Class, you'll find Class FirstWizardPage. In createControl method, a DataBindingContext is instantiated at first, no news right here. The binding is created with this code:

	dbc.bindValue(SWTObservables.observeText(text, SWT.Modify),
		((SampleWizard) getWizard()).getModel().intValue,
		new UpdateValueStrategy().setAfterConvertValidator(new SingleDigitValidator()),
		null);

Oooh, what a monster. Fortunately, you have already some good knowledge to understand whats going on here. The first parameter is a Target IObservableValue bound to the Wizards Text control. It's provided with a SWT.Modify event, which means that anytime, the controls text changes, the Data Binding mechanism is invoked. The second parameter is the already dicussed WritableValue. Remember, it's an IObservableValue implementation, so again, we deal with two Observables. The third parameter ist the most interessting and new part of the story: first, a new UpdateValueStrategy is instantiated. This is required, when you have to deal with:

  • Validation
  • Conversion
  • Automatic processing

in your binding.

It offers five phases for manipulation where you can hook on:

  • Validate after get
  • Conversion
  • Validate after conversion
  • Validate before set
  • Value set

You may have a look to the UpdateValueStrategy JavaDocs, which are quite voluminously documented, for further information.

In our case, the method setAfterConvertValidator(IValidator validator) is called, which invokes the validator after the source value is converted to the type of the destination observable. setAfterConvertValidator eats an IValidator as param. This one is offered as another inner Class nested in Class FirstWizardPage. It simply checks, whether incoming value is between 0 and 9. If not, a ValidationStatus(IStatus.ERROR, message) is returned, resulting WizardPage1 moaning about the wrong value:

Snippet014WizardDialog.JPG

Binding Collections


MasterDetail Binding


ObservablesManager