【问题标题】:Vaadin: Bind Enum values to ComboBox (ConversionException)Vaadin:将枚举值绑定到 ComboBox (ConversionException)
【发布时间】:2016-09-07 08:54:30
【问题描述】:

我想将我的模型中的枚举值绑定到 ComboBox。我尝试了什么:

型号:

public class Model{
public enum Status {
        Neu, Analyse, Pruefung, Freigabe, OnTheRoad, EOL, CANCELLED;
        public String getCaption() {
            return name();
        }

        public int getId() {
            return ordinal();
        }
    }

    private Status status;
}

表格:

public class MyForm extends CustomComponent{

private final BeanFieldGroup<Model> binder;

@PropertyId("status")
 private final ComboBox cStatus = new ComboBox("Status");

public MyForm (Model model) {
        final HorizontalLayout content = new HorizontalLayout();
        content.addComponent(buildContent());

        // Now use a binder to bind the members
        binder = new BeanFieldGroup<>(Model.class);

        // We need an item data source before we create the fields to be able to
        // find the properties, otherwise we have to specify them by hand
        final BeanItem bean = new BeanItem<>(model);
        binder.setItemDataSource(bean);
        binder.buildAndBindMemberFields(this);

        setCompositionRoot(content);
}

private buildContent(){
        final FormLayout basicContent = new FormLayout();

        final BeanContainer<Integer, Status> container = new BeanContainer<>(Status.class);
        container.setBeanIdProperty("id");
        container.addAll(EnumSet.allOf(Status.class));
        cStatus.setContainerDataSource(container);
        cStatus.setItemCaptionPropertyId("caption");
        basicContent.addComponent(cStatus);

        return basicContent;
}

public void commit() throws CommitException {
        binder.commit(); // This is what causes the error
}
}

当我调用 commit() 时出现此错误:

Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class com.xx.test.entities.def.Model$Status. No converter is set and the types are not compatible.
    at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:751) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:731) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.ui.AbstractField.getConvertedValue(AbstractField.java:817) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.ui.AbstractField.commit(AbstractField.java:253) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.data.fieldgroup.FieldGroup.commitFields(FieldGroup.java:509) ~[vaadin-server-7.5.6.jar:7.5.6]
    at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:481) ~[vaadin-server-7.5.6.jar:7.5.6]
    ... 49 more

有没有办法将我的模型的枚举绑定到组合框?

感谢您的帮助!

更新(André Schild 回答):

我想显示枚举值的字符串表示,所以我认为我需要使用字符串而不是整数?我发现实际上在“StringToEnumConverter”中有一个构建。但是,我使用 StringToEnumConverter 和我自己的“StringToStatusConverter”进行了尝试:

cStatus.setConverter((Converter) new StringToEnumConverter());
cStatus.addItems(EnumSet.allOf(Status.class));`
// cStatus.addItem(Status.CANCELLED); // Did not work
// cStatus.setConvertedValue(Status.EOL); // Did not work

现在我得到:

java.lang.ClassCastException: xx.xxx.xxx.entities.modeldefdef.Model$Status cannot be cast to java.lang.String
    at com.vaadin.data.util.converter.StringToEnumConverter.convertToModel(StringToEnumConverter.java:32) ~[vaadin-server-7.5.6.jar:7.5.6]

...对于两个转换器。

【问题讨论】:

    标签: java data-binding combobox enums vaadin


    【解决方案1】:

    在你的 buildContent() 方法中写:

    // ...
    final BeanItemContainer<Status> container = new BeanItemContainer<>(Status.class);
    container.addAll(EnumSet.allOf(Status.class));
    cStatus.setContainerDataSource(container);
    cStatus.setItemCaptionPropertyId("caption");
    basicContent.addComponent(cStatus);
    // ...
    

    为什么?您的 ComboBox 由您的 FieldGroup 绑定到 Status 类型的属性。但是您当前的 Container BeanContainer 具有 Integer 类型,即容器 ID 的类型。要修复容器的 ID 类型必须匹配属性的类型。这是通过使用 BeanItemContainer 完成的,它使用 Bean 类型作为对象 ID。 Here这个问题解释的比较详细。

    【讨论】:

    • 添加container.setBeanIdProperty("id");后,枚举可以应用到组合框。唯一导致仍然出现问题的原因是在我持久化对象之前调用binder.commit();。这是错误消息:Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class xx.xxx.xx.entities.xxxxxdef.Model$Status. No converter is set and the types are not compatible. at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181) ~[vaadin-server-7.5.6.jar:7.5.6]
    • 你需要实现一个实现Converter的转换器!这是因为 Container 的表现类型是 Object。在该容器中,您将状态对象转换为整数,反之亦然。不过,在这里使用 BeanItemContainer 比使用带有整数作为 ID 的 BeanContainer 简单得多。
    • 查看上述页面 (blog.oio.de/2014/04/25/…) 上的转换器。重要的部分是“将项目 ID 类型和属性类型结合在一起”。
    • 对不起,我的错。我使用BeanContainer 而不是BeanItemContainer。现在它可以正常工作了,谢谢!
    【解决方案2】:

    Vaadin 有Converter 的概念,它从内部表示转换为外部表示。

    您需要实现 Converter 接口,然后指定使用它。

    public class IntegerToModelStatusConverter implements Converter<Integer, Model$Status>
    

    final ComboBox statusField = new ComboBox("Status");
    statusField .setConverter(new IntegerToModelStatusConverter());
    

    整数是对应枚举元素的int值。

    有一个wiki 条目对此进行了更详细的描述。

    【讨论】:

    猜你喜欢
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2014-01-26
    • 1970-01-01
    • 2016-09-15
    • 2010-10-29
    • 2015-07-03
    相关资源
    最近更新 更多