Question

I want to bind an indexed property to JFace ComboViewer.

Lets say that I have a DataModel class like this:

class DataModel {
   private String[] props = {"A","B","C"};
   private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

   public String getProperties( int idx ){
      return props[idx];
   }

   public void setProperties( int idx, String value ){
      String oldVal = props[idx];
      props[idx] = value;
      pcs.fireIndexedPropertyChange( "properties", idx, oldVal, value );
   }

   // code to add/remove PropertyChangeListener
   // ...
}

The data binding code for simple property would look like this:

DataModel dataModel = ...
ComboViewer propertyChoice = ...

DataBindingContext ctx = new DataBindingContext();

IObservableValue target = ViewerProperties.singleSelection().observe( propertyChoice );
IObservableValue model = BeanProperties.value( DataModel.class, "properties" ).observe(dataModel);
ctx.bindValue( target, model ); 

but with an indexed property I have to inform the ctx at which index is the value that I want to bind. I have tried

IObservableValue model = BeanProperties.value( DataModel.class, "properties[0]" ).observe(dataModel);

but it doesn't work.

Is it possible to bind indexed property instead of simple property? How?

Était-ce utile?

La solution

Unfortunately this seems to be unsupported. I was looking for exactly the same functionality. There is no documentation in BeanProperties that says it is supported.

When looking into the implementation of BeanProperties.value, you find that it delegates to BeanPropertyHelper for reading and writing a property. The method Object readProperty(Object source, PropertyDescriptor propertyDescriptor) does not know about the subclass IndexedPropertyDescriptor. When it is invoked for an indexed property, readProperty tries to use a read method that reads the entire array. I think this method is optional for indexed properties. For indexed properties it should use the IndexedPropertyDescriptor.getIndexedReadMethod().

Depending on your use case you may be able to workaround the problem by using BeanProperties.list. However you cannot use this in combination with indexed properties. I tried this by adding a method that returns the entire array but still keeping the method that does a "fireIndexedPropertyChange". Unfortunately this gives a ClassCastException: Eclipse's BeanListProperty seems to suppose that the value in the change event is an array or list. However for an indexed property it is a single element of the array.

Or perhaps you can use an observable map instead?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top