- Observe changes of the viewer's selection.
- Observe the name property of the selection.
Bind the text of the Text widget to the name detail (selected person's name).
In the 2 steps we're concerned with we have 3 players:
- viewer - maintains a reference to the selection and provides change events when it changes
- selection (person)- maintains a reference to the name and provides change events when it changes
- name - value to display
If using dot notation we'd be able to access the value of the detail with something like the following (assuming the selection is not null)...
viewer.selection.name
If we genericize the roles a bit we get...
container.master.detail
The Pattern
The master detail APIs will satisfy your use case if...
- you need to observe
container.master.detail
- AND the
master
instance can be replaced over time
Non Selection Use Case
A use case that arose recently on the newsgroup was how to setup the binding to a Person model that can be replaced over time. This was in the context of implementing presentation model. The following code was being used as the presentation model.
class ViewModel {
private Person person;
public void getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Over time a new person would be set and the UI had to update. Expressed in dot notation this was
viewModel.person.name
. The only change that needed to occur to the code was that ViewModel needed to fire change events for Person and then the binding was wired up like normal.
class ViewModel {
private Person person;
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(propertyName, listener);
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
changeSupport.firePropertyChange("person", this.person, this.person = person);
}
}
// Create an observable to observe changes in the view model
IObservableValue personValue = BeansObservables.observeValue(
viewModel, "person");
//Bind to the name detail of the current person
dbc.bindValue(SWTObservables.observeText(form.getTextName(),
SWT.Modify), BeansObservables.observeDetailValue(Realm
.getDefault(), personValue, "name",
String.class), null);
WritableValue, for those looking for a shortcut
If you're in a position where it doesn't matter if your model is a java bean, look into one of my favorite classes WritableValue. Your code then becomes...
class ViewModel {
/**
* observable value to maintain the person instance
*/
private IObservableValue personObservable = new WritableValue(Person.class);
public IObservableValue getPersonObservable() {
return personObservable;
}
}
//Observe the detail.
IObservableValue detailObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), viewModel.getPersonObservable(), "name",
String.class);
Code to set the person would be...
viewModel.getPersonObservable().setValue(person);
3 comments:
i read your post and it's ok when you use "static" detail view.
if you create i.e. 2 composites :
the first contains a list viewer
the second some text widgets that show details.
you can setup a observeDetailValue binding to fill the widgets with values from selection.
but when you use the master - detail implementation from ui.form package where detail pages are created "on the fly" on selection change, your pattern doesn't works.
I can't figure out a simple solution for this case.
have u any ideas? :)
i hope you can understand what i wrote.
giulio
You have me at a bit of a disadvantage as I'm not familiar with the ui.forms master detail. But I'm assuming that you have lifecycle events for when the detail view is created and when it's disposed. Correct? If the view is transient and changes depending upon the selection I don't think you need the Data Binding master detail APIs. All you would do would be to retrieve the object from the selection, bind your UI, and you're done. Then when a new selection is made a new view is created and you repeat. It would seem that the Data Binding master detail APIs only make sense when you have a, as you say, static view.
i'm posting here how i solved it. Maybe someone can consider it useful.
I have a FormEditor which contains a master and details parts. When master fires a selection event, a new detail page will be instantiated and the selected object is passed to detail page through the selectionChanged method.
So in this method we have to setup our binding.
MasterDetailsBlock usually try to reuse the same instance of detail part and don't instantiate a new one for every selection.
So in selectionChanged code we have to check if we have already a bindingcontex instance, dispose it, and create a new one.
i wish that what i wrote can be comprensible and usefull for someone.
in databinding there is still some work to do for a better support of form and more specific API, but the project is great.
Soon I'll try to find the time to write small tutorials on databinding (probably in italian) because there are too few docs about it.
:)
thx
giulio
Post a Comment