Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "JFace Data Binding/Tutorial"

(A first simple binding)
(Data Binding Tutorial)
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
== Data Binding Tutorial ==
 
== Data Binding Tutorial ==
 
--[[User:Frank.schaare.gmail.com|Frank.schaare.gmail.com]] 20:24, 12 October 2007 (EDT)
 
--[[User:Frank.schaare.gmail.com|Frank.schaare.gmail.com]] 20:24, 12 October 2007 (EDT)
 +
 +
This tutorial is not yet updated to use the new Properties API which is as of Eclipse 3.5 the recommended way of using databinding. For a tutorial which uses the Properties API please see [http://www.vogella.com/articles/EclipseDataBinding/article.html Eclipse JFace Databinding and Validation - Tutorial]
 
=== Terms ===
 
=== Terms ===
 
----
 
----
Line 33: Line 35:
 
}
 
}
 
</pre>
 
</pre>
<p>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.</p>
+
<p>As you may have noticed, the Person class extends '''ModelObject'''. 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.</p>
 
<p>To create your first binding, you need to instantiate a '''DataBindingContext'''. Create a method like this:</p>
 
<p>To create your first binding, you need to instantiate a '''DataBindingContext'''. Create a method like this:</p>
 
<pre>
 
<pre>
 
private DataBindingContext initDataBindings() {
 
private DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
+
        DataBindingContext bindingContext = new DataBindingContext();
  
return bindingContext;
+
        return bindingContext;
 
}
 
}
 
</pre>
 
</pre>
Line 45: Line 47:
 
<pre>
 
<pre>
 
private DataBindingContext initDataBindings() {
 
private DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
+
        DataBindingContext bindingContext = new DataBindingContext();
  
        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
+
                IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
  
return bindingContext;
+
        return bindingContext;
 
}
 
}
 
</pre>
 
</pre>
Line 61: Line 63:
 
<pre>
 
<pre>
 
private DataBindingContext initDataBindings() {
 
private DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
+
        DataBindingContext bindingContext = new DataBindingContext();
        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
+
  
IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");
+
                IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
 +
        IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");
  
return bindingContext;
+
        return bindingContext;
 
}
 
}
 
</pre>
 
</pre>
Line 78: Line 80:
 
<pre>
 
<pre>
 
private DataBindingContext initDataBindings() {
 
private DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
+
        DataBindingContext bindingContext = new DataBindingContext();
        IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
+
IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");
+
  
bindingContext.bindValue(nameTextObserveWidget, personNameObserveValue, null, null);
+
                IObservableValue nameTextObserveWidget = SWTObservables.observeText(name, SWT.FocusOut);
 +
        IObservableValue personNameObserveValue = BeansObservables.observeValue(person, "name");
  
return bindingContext;
+
        bindingContext.bindValue(nameTextObserveWidget, personNameObserveValue, null, null);
 +
 
 +
        return bindingContext;
 
}
 
}
 
</pre>
 
</pre>
Line 111: Line 114:
 
<p>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:</p>
 
<p>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:</p>
 
<pre>
 
<pre>
dbc.bindValue(SWTObservables.observeText(text, SWT.Modify),
+
dbc.bindValue(
 +
                SWTObservables.observeText(text, SWT.Modify),
 
((SampleWizard) getWizard()).getModel().intValue,
 
((SampleWizard) getWizard()).getModel().intValue,
 
new UpdateValueStrategy().setAfterConvertValidator(new SingleDigitValidator()),
 
new UpdateValueStrategy().setAfterConvertValidator(new SingleDigitValidator()),
null);
+
null
 +
        );
 
</pre>
 
</pre>
 
<p>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:
 
<p>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:
Line 135: Line 140:
 
<p>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:</p>
 
<p>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:</p>
 
[[Image:Snippet014WizardDialog.JPG]]
 
[[Image:Snippet014WizardDialog.JPG]]
 
=== Binding Collections ===
 
----
 
=== MasterDetail Binding ===
 
 
----
 
 
=== ObservablesManager ===
 
 
----
 

Revision as of 12:59, 10 May 2012

Data Binding Tutorial

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

This tutorial is not yet updated to use the new Properties API which is as of Eclipse 3.5 the recommended way of using databinding. For a tutorial which uses the Properties API please see Eclipse JFace Databinding and Validation - Tutorial

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 ModelObject. 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

Back to the top