Eclipse - Binding (ab Eclipse 3.3)
JFace-Data-Binding ab Eclipse 3.3
In einem gedachten Beispiel soll ein Model aus den drei Attributen
- Nachname
- Vorname
- Geburtsdatum
bestehen.
Binding-Methode
Die Binding-Methode kann beispielsweise in der MyFormPart-Klasse implementiert werden.
private void bind(model) { m_bindingContext = new DataBindingContext(); // Das Textfeld "m_lastnameTxt" für den Nachnamen an das Model-Attribut "m_lastname" binden: m_bindingContext.bindValue(SWTObservables.observeText(m_lastnameTxt, SWT.Modify), BeansObservables.observeValue(model, MyModel.PROP_LASTNAME), null, null); // Das Textfeld "m_firstnameTxt" für den Nachnamen an das Model-Attribut "m_firstname" binden: m_bindingContext.bindValue(SWTObservables.observeText(m_firstnameTxt, SWT.Modify), BeansObservables.observeValue(model, MyModel.PROP_FIRSTNAME), null, null); // Das Textfeld "m_birthdateTxt" für den Nachnamen an das Model-Attribut "m_birthday" binden: m_bindingContext.bindValue(SWTObservables.observeText(m_birthdateTxt, SWT.Modify), BeansObservables.observeValue(model, MyModel.PROP_BIRTHDAY), m_targetToModelStrategy, m_modelToTargetStrategy); // UpdateStrategy initialisieren (Konverter und Validatoren festlegen): initUpdateStrategy(); }
Der Aufruf erfolgt dann in der setFormInput(..) Methode:
@Override public boolean setFormInput(final Object input){ MyModel model = (MyModel)input; bind(model); }
Methode initUpdateStrategy()
Da diese Methode von der bind()-Methode aufgerufen wird, muss sie natürlich für diese erreichbar sein.
private void initUpdateStrategy(){ IConverter date2StrConverter = new IConverter() { public Object convert(Object fromObject) { assert fromObject instanceof Date; Date date = (Date) fromObject; SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy"); return sdf.format(date); } public Object getFromType() { return Date.class; } public Object getToType() { return String.class; } }; IConverter str2DateConverter = new IConverter() { public Object convert(Object fromObject) { assert fromObject instanceof String; String str = (String) fromObject; SimpleDateFormat sd = new SimpleDateFormat("dd.MM.yyyy"); Date date = null; try { Date newDate = sd.parse(dateString); } catch (Exception e) { e.printstacktrace(); } return date; } public Object getFromType() { return String.class; } public Object getToType() { return Date.class; } }; IValidator dateFormatValidator = new IValidator() { public IStatus validate(Object value) { assert value instanceof String; IStatus status = Status.OK_STATUS; String str = (String) value; if (str.matches("\\d{2}\\.\\d{2}\\.\\d{4}")) { try { DateConv.toDate(str); }catch(IllegalArgumentException e) { status = ValidationStatus.error("Wrong Date", e); } }else status = ValidationStatus.error("Wrong Format"); return status; } }; IValidator dateBizValidator = new IValidator() { public IStatus validate(Object value) { IStatus status = Status.OK_STATUS; Date inspect = (Date) value; if (null != inspect) { final Date today = new Date(); if (today.before(inspect)) status = ValidationStatus.error("Datum muss vor heute liegen!"); } return status; } }; m_modelToTargetUpdateStrategy1 = new UpdateValueStrategy(); // oder bei spezieller Policy (Default: UpdateValueStrategy.POLICYUPDATE) // m_modelToTargetUpdateStrategy1 = new UpdateValueStrategy(UpdateValueStrategy.NEVER); m_modelToTargetUpdateStrategy1.setConverter(date2StrConverter); m_targetToModelUpdateStrategy = new UpdateValueStrategy(); m_targetToModelUpdateStrategy.setConverter(str2DateConverter); m_targetToModelUpdateStrategy.setAfterGetValidator(dateFormatValidator); m_targetToModelUpdateStrategy.setBeforeSetValidator(dateBizValidator); }
Model-Klasse
package com.sowas.demo; import java.beans.PropertyChangeListener; public class MyModel { String PROP_LASTNAME = "lastname"; String PROP_FIRSTNAME = "firstname"; String PROP_BIRTHDAY = "birthday"; private final PropertyChangeSupport m_propertyChangeSupport = new PropertyChangeSupport(); private String m_lastname; private String m_firstname; private Date m_birthday; public MyModel(String lastname, String firstname, Date birthday) { m_lastname = lastname; m_firstname = firstname; m_birthday = birthday; } public String getLastname(){ return m_lastname; } public void setLastname(final String newValue){ String oldValue = getLastname(); m_lastname = newValue; firePropertyChange(PROP_LASTNAME, oldValue, newValue); } public String getFirstname(){ return m_firstname; } public void setFirstname(final String newValue){ String oldValue = getFirstname(); m_firstname = newValue; firePropertyChange(PROP_FIRSTNAME, oldValue, newValue); } public Date getBirthday(){ return m_birthday; } public void setBirthday(final Date newValue){ Date oldValue = getBirthday(); m_birthday = newValue; firePropertyChange(PROP_BIRTHDAY, oldValue, newValue); } protected boolean firePropertyChange(final String propertyName, final Object oldValue, final Object newValue) { return m_propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } public void addPropertyChangeListener(final PropertyChangeListener listener, final String... propertyNames) { m_propertyChangeSupport.addPropertyChangeListener(listener, propertyNames); } public void addPropertyChangeListener(final PropertyChangeListener listener) { m_propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(final PropertyChangeListener listener, final String... propertyNames) { m_propertyChangeSupport.removePropertyChangeListener(listener, propertyNames); } public void removePropertyChangeListener(final PropertyChangeListener listener) { m_propertyChangeSupport.removePropertyChangeListener(listener); } }
Button-Enablement an Validationstatus binden
public void bindButtonEnablementToValidationStatus(final Button button) { final IObservableValue buttonEnable = SWTObservables.observeEnabled(button); final IObservableValue validationStatus = new AggregateValidationStatus(myBindingContext.getValidationRealm(), myBindingContext.getBindings(), AggregateValidationStatus.MAX_SEVERITY); myBindingContext.bindValue(buttonEnable, validationStatus, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter(new Converter(IStatus.class, Boolean.TYPE) { @Override public Object convert(final Object fromObject) { return new Boolean(((IStatus) fromObject).isOK()); } })); }
Fehlersuche
Wird eine setXYZ(..)-Methode nicht gefunden, so sollte als Erstes die Schreibweise der Property-Konstanten (hier: PROP_XXXXX) überprüft werden. Diese muss genauso geschrieben werden wie die get und set-Methoden. Lediglich das get und set wird weggelassen und der erste Buchstabe wird kleingeschrieben.
Beispiel:
es gäbe die Methoden getValue() und setValue(int newValue), so müsste die Konstante als „value“ definiert werden.
Beispiel:
public static final String PROP_VALUE = "value";
Als Zweites kann man einen Breakpoint in der Methode ValueBinding#doUpdate(..) setzen (z.B. beim Aufruf der Methode updateValueStrategy.doSet(..)) um den Fehler zu finden.
Achtung! In Eclipse 3.3 gibt es einen Fehler: Die PropertyMethode/die Property-Konstante darf niemals mit zwei Großbuchstaben beginnen (also nicht: getVAlue() mit „vAlue“)!!