简而言之: 我在编辑模式下每个字段中的组合框在选择项目时给出了转换错误,但是相同的逻辑和容器在TableFieldFactory(createField())。我做错了什么?
更长的解释: 我有一个包含多个属性(列)和项(行)的容器。当我编辑连接到此容器的表时,我想在某些列字段上使用组合框。我正在使用TableFieldFactory,它就像一个魅力。
我希望每个字段中的组合框包含来自其各自属性的 distinct 元素。我的解决方案是在我的Container类中实现一个迭代容器中所有属性的方法,并为每个属性创建一个具有该属性的唯一值的新IndexedContainer。该方法返回一个带有PropertyIds / Containers的映射,这样我在createField()中就可以从我希望拥有组合框的每个属性中选择每个容器。
示例
所以,说我有三个propertyId,Foo,Bar和Baz,每个“包含”几个项目,其中一些是相同的,如下所示:
富
......和Bar和Baz一样,只有其他值......
getDistinctContainers()方法返回 Map ,如下所示:
Key: PropertyId: Foo
Value: Container: contains propertyId [Foo] and the unique values of Foo, ie. [Chris, Meg, Stewie]
Key: PropertyId: Bar
Value: ... and so forth...
当我要在createField()中设置容器数据源时,容器看起来像这样(对于属性Foo):
allItemIds: [0, 1, 2]
items: {2={Foo=Stewie}, 1={Foo=Meg}, 0={Foo=Chris}}
propertyIds: [Foo]
......对我来说似乎没问题......
现在,该表按预期显示每个字段中的组合框。但是,当我单击组合框中的项目时,它会给出以下转换错误:
com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class java.lang.String. No converter is set and the types are not compatible.
at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181)
at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:745)
注意:
我尝试在表外创建相同的场景,并且它运行得很好。因此,似乎具有相同逻辑和相同容器的组合框在TableFieldFactory和createFields()方法之外工作正常。我无法理解他们为什么不能在TableFieldFactory中工作......
问题:
这是我的Container类:
public class SomeContainer extends IndexedContainer {
private static final long serialVersionUID = 1L;
public void addContainerProperties() {
addContainerProperty("Foo", String.class, null);
addContainerProperty("Bar", String.class, null);
addContainerProperty("Baz", String.class, null);
}
public Map<String, Container> getDistinctContainers() {
Map<String, Container> m = new HashMap<String, Container>();
ArrayList<Object> filter = new ArrayList<Object>();
int id = 0;
for (Object propertyId : this.getContainerPropertyIds()) {
Container cont = new IndexedContainer();
cont.addContainerProperty(propertyId, propertyId.getClass(), null);
for (Object itemId : this.getItemIds()) {
Object ob = ((Item) this.getItem(itemId)).getItemProperty(propertyId).getValue();
if ((!filter.contains(ob.toString())) && (ob != null)) {
filter.add(ob.toString());
Item item = cont.addItem(id);
item.getItemProperty(propertyId).setValue(ob);
id++;
}
}
m.put(propertyId.toString(), cont);
}
return m;
}
}
...这里是createField的相关代码:
@Override
public Field<?> createField(Container container, Object itemId, Object propertyId, com.vaadin.ui.Component uiContext) {
TextField tField = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId, uiContext);
tField.setImmediate(true);
// ...some code here that uses the TextField
if (propertyId.equals("Foo")) {
ComboBox select = new ComboBox();
for (Map.Entry<String, Container> entry : distinctContainers.entrySet()) {
if (entry.getKey().equals(propertyId)) {
select.setContainerDataSource(entry.getValue());
}
}
select.setImmediate(true);
select.setItemCaptionPropertyId(propertyId);
select.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY);
return select;
}
// ... if statements for Bar and Baz left out for brevity...
return tField;
}
请帮助我理解我缺少的东西!
提前致谢!
答案 0 :(得分:1)
从上面的异常和代码片段中我们可以看到需要Integer
(演示文稿类型)和String
(模型)之间的转换。在这种特殊情况下:
由于Vaadin没有内置的IntegerToStringConverter,你需要一个自定义转换器:
...
select.setContainerDataSource(entry.getValue());
select.setConverter(new Converter<Object, String>() {
@Override
public String convertToModel(Object itemId, Class<? extends String> paramClass, Locale paramLocale) throws ConversionException {
if (itemId != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
Object name = c.getItem(itemId).getItemProperty(propertyId).getValue();
return (String) name;
}
return null;
}
@Override
public Object convertToPresentation(String value, Class<? extends Object> paramClass, Locale paramLocale) throws ConversionException {
if (value != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
for (Object itemId : container.getItemIds()) {
Object name = c.getContainerProperty(itemId, propertyId).getValue();
if (value.equals(name)) {
return itemId;
}
}
}
return null;
}
@Override
public Class<String> getModelType() {
return String.class;
}
@Override
public Class<Object> getPresentationType() {
return Object.class;
}
});
请注意,无法使用显式的Integer&lt; - &gt;字符串转换
select.setConverter(new Converter<Integer, String>());
因为编译器拒绝它。问题已经描述here。
有关Vaadin转换器的更多信息,请访问:
Book of Vaadin, Chapter 9.2.3: Converting Between Property Type and Representation
Changing the default converters for an application
Creating your own converter for String - MyType conversion
我希望它有所帮助。