Vaadin Web应用开发教程(42):数据绑定-Property接口

jerry VaadinWeb 2015年11月25日 收藏

Property接口为Vaadin数据模型的基本接口,它提供了读写单个数据对象的标准API。 一个Property对象总是有数据类型的,尽管它支持可选的数据类型转换。Property的数据可以为任意的Java对象,Property 也提供了监听数据变化的事件消息。
Property的读写方法为getValue()和setValue() 。getValue() 返回通用的Object 类型的对象,因此可以强制转换成所需的数据类型。Property的类型可以通过getType()取得。
Property值发生变化说触发ValueChangeEvent事件,可以通过ValueChangeListener监听这个事件。

  1. final TextField tf = new TextField("Name");
  2. // Set the value
  3. tf.setValue("The text field value");
  4. // When the field value is edited by the user
  5. tf.addListener(new Property.ValueChangeListener() {
  6. public void valueChange(ValueChangeEvent event) {
  7. // Get the value and cast it to proper type
  8. String value = (String) tf.getValue();
  9. // Do something with it
  10. layout.addComponent(new Label(value));
  11. }
  12. });

使用Property接口,一是实现Property接口,而是使用Vaadin内置的两个Property接口实现:MethodProperty 主要用于Java Bean,而是ObjectProperty用于简单的Java对象。

与Property接口关系紧密的还有两个接口Property.EditorProperty.Viewer 可以用来显示和编译Property值,大部分的UI组件,尤其是Field组件实现了这两个接口,因此Field组件可以直接绑定到Property对象,用来显示或编辑Property数据。

下例使用Label 来显示一个ObjectProperty 对象

  1. // Have a data model
  2. ObjectProperty property =
  3. new ObjectProperty("Hello", String.class);
  4. // Have a component that implements Viewer
  5. Label viewer = new Label();
  6. // Bind it to the data
  7. viewer.setPropertyDataSource(property);

同样可以使用一个TextField来编辑并显示一个ObjectProperty对象

  1. // Have a data model
  2. ObjectProperty property =
  3. new ObjectProperty("Hello", String.class);
  4. // Have a component that implements Viewer
  5. TextField editor = new TextField("Edit Greeting");
  6. // Bind it to the data
  7. editor.setPropertyDataSource(property);

前面说过所有Field组件也实现了Property接口,因此也可以把Field组件绑定到实现了Property.Viewer接口的UI组件,如Label。下例把一个Label绑定到一个TextField,因此Label显示的内容会和TextField的值变化而变化。

  1. Label viewer = new Label();
  2. viewer.setPropertyDataSource(editor);
  3. // The value shown in the viewer is updated immediately
  4. // after editing the value in the editor (once it
  5. // loses the focus)
  6. editor.setImmediate(true);

此外,你也可以自行实现Property接口,然后绑定到Field组件。

  1. class MyProperty implements Property {
  2. Integer data = 0;
  3. boolean readOnly = false;
  4. // Return the data type of the model
  5. public Class<?> getType() {
  6. return Integer.class;
  7. }
  8.  
  9. public Object getValue() {
  10. return data;
  11. }
  12. // Override the default implementation in Object
  13. @Override
  14. public String toString() {
  15. return Integer.toHexString(data);
  16. }
  17.  
  18. public boolean isReadOnly() {
  19. return readOnly;
  20. }
  21.  
  22. public void setReadOnly(boolean newStatus) {
  23. readOnly = newStatus;
  24. }
  25.  
  26. public void setValue(Object newValue)
  27. throws ReadOnlyException, ConversionException {
  28. if (readOnly)
  29. throw new ReadOnlyException();
  30. // Already the same type as the internal representation
  31. if (newValue instanceof Integer)
  32. data = (Integer) newValue;
  33. // Conversion from a string is required
  34. else if (newValue instanceof String)
  35. try {
  36. data = Integer.parseInt((String) newValue, 16);
  37. } catch (NumberFormatException e) {
  38. throw new ConversionException();
  39. }
  40. else
  41. // Don't know how to convert any other types
  42. throw new ConversionException();
  43.  
  44. // Reverse decode the hexadecimal value
  45. }
  46. }
  47. // Instantiate the property and set its data
  48. MyProperty property = new MyProperty();
  49. property.setValue(42);
  50. // Bind it to a component
  51. final TextField tf = new TextField("Name", property);