Generics 导叶选择过滤柱<;T、 布尔值>;带有NullValid(ConversionException)

Generics 导叶选择过滤柱<;T、 布尔值>;带有NullValid(ConversionException),generics,wicket,filtering,Generics,Wicket,Filtering,我想创建一个ChoiceFilteredPropertyColumn,以布尔值作为支持模型 我的问题是,我想在下拉列表中有第三个选择,“选择一个”。我通过覆盖newDropDownChoice并将nullValid设置为true(如这里所建议的那样)来添加它 但是选择此值时会抛出ConversionException,因为支持模型是布尔值 我的问题是,;当选择此值时,是否有方法拦截?通过这种方式,我可以将一个标志传递给进行过滤查询的位置,即忽略布尔值的当前值 (我不能更改支持模型。我不能有另一个

我想创建一个ChoiceFilteredPropertyColumn,以布尔值作为支持模型

我的问题是,我想在下拉列表中有第三个选择,“选择一个”。我通过覆盖newDropDownChoice并将nullValid设置为true(如这里所建议的那样)来添加它 但是选择此值时会抛出ConversionException,因为支持模型是布尔值

我的问题是,;当选择此值时,是否有方法拦截?通过这种方式,我可以将一个标志传递给进行过滤查询的位置,即忽略布尔值的当前值

(我不能更改支持模型。我不能有另一个支持模型,比如说字符串,以后用于设置布尔值)

提前谢谢

在伯尼建议后编辑:

    @Override
    public Component getFilter(final String componentId, final FilterForm<?> form) {
    ChoiceFilter<F> filter = new ChoiceFilter<F>(componentId, getFilterModel(form), form, super.getFilterChoices(), enableAutoSubmit()) {

    private static final long serialVersionUID = 1L;

    @Override
    protected DropDownChoice<F> newDropDownChoice(String id, IModel<F> model, IModel<List<? extends F>> choices, IChoiceRenderer<F> renderer) {
        DropDownChoice<F> dropDownChoice = new DropDownChoice<F>(id, model, choices, renderer) {

            private static final long serialVersionUID = 1L;

            @Override
            public <C> IConverter<C> getConverter(Class<C> type) {
                super.getConverter(type);
                BooleanConverter test = new BooleanConverter() {

                    private static final long serialVersionUID = 1L;

                    @Override
                    public Boolean convertToObject(String value, Locale locale) {
                        System.out.println("I'm never printed :(");
                        return super.convertToObject(value, locale);
                    }

                    @Override
                    public String convertToString(Boolean value, Locale locale) {
                        return super.convertToString(value, locale);
                    }

                };

                return (IConverter<C>) test;
            }

        };
        dropDownChoice.setNullValid(true);
        return dropDownChoice;
    }
};

IChoiceRenderer<F> renderer = getChoiceRenderer();
if (renderer != null) {
    filter.getChoice().setChoiceRenderer(renderer);
}
return filter;
}
@覆盖
公共组件getFilter(最终字符串componentId,最终FilterPerform表单){
ChoiceFilter筛选器=新的ChoiceFilter(组件ID、getFilterModel(表单)、表单、super.getFilterChoices()、enableAutoSubmit()){
私有静态最终长serialVersionUID=1L;
@凌驾

受保护的DropDownChoice newDropDownChoice(字符串id、IModel模型、IModel对不起,DropDownChoice不会使用转换器,而是搜索其选项列表(通过ChoicesRenderer)以转换为对象

我不是100%确定我理解,但这里有一些东西你可以试试:

重写
ChoiceFilteredPropertyColumn
的方法
public Component getFilter(final String componentId,final filter form)
,以提供
ChoiceFilter
的子类。此子类应重写
getConverter(Class)
返回接受空值的
BooleanConverter
的实现

或者,注册您自己的
布尔转换器
应用程序
级别全局接受所有布尔值的空值

IMHO,这应该作为JIRA问题提交。许多(所有?)其他转换器检查空输入,在这种情况下返回空

也就是说,我在Wicket 1.5.5上试用了您的用例,效果非常好!您自己试试:

html

ApacheWicket快速入门
JAVA
package com.wicketTest.tables;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Iterator;
导入java.util.List;
导入java.util.Random;
导入org.apache.wicket.Component;
导入org.apache.wicket.iclusteable;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.filter.ChoiceFilter;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.filter.choiceFilteredProperty列;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.filter.FilterPerform;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.filter.FilterToolbar;
导入org.apache.wicket.extensions.markup.html.repeater.data.table.filter.IFilterStateLocator;
导入org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
导入org.apache.wicket.markup.html.WebPage;
导入org.apache.wicket.markup.html.form.DropDownChoice;
导入org.apache.wicket.markup.html.form.ichoicerender;
导入org.apache.wicket.model.IModel;
导入org.apache.wicket.model.LoadableDetachableModel;
导入org.apache.wicket.model.model;
导入org.apache.wicket.request.mapper.parameter.PageParameters;
公共类ChoiceFilterPage扩展网页{
私有数组列表数据;
公共选择过滤公司(页面参数){
超级(参数);
//提供者
数据=新的ArrayList();
对于(int i=0;i<10;i++){
数据。添加(新内容(正确));
}
提供程序=新提供程序();
//形式
FilterForm=新的FilterForm(“表格”,提供者);
添加(表格);
//纵队
列表列=新的ArrayList();

谢谢你的回复。我试过了,但没法让它工作,也许我误解了什么。编辑中的代码。
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8" />
<title>Apache Wicket Quickstart</title>
</head>
<body>
    <form wicket:id="form">
    <table wicket:id="table"></table>
    </form>
</body>
</html>
package com.wicketTest.tables;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.apache.wicket.Component;
import org.apache.wicket.IClusterable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.filter.ChoiceFilter;
import org.apache.wicket.extensions.markup.html.repeater.data.table.filter.ChoiceFilteredPropertyColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.filter.FilterForm;
import org.apache.wicket.extensions.markup.html.repeater.data.table.filter.FilterToolbar;
import org.apache.wicket.extensions.markup.html.repeater.data.table.filter.IFilterStateLocator;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.mapper.parameter.PageParameters;

public class ChoiceFilterPage extends WebPage {

    private ArrayList<Stuff> data;

    public ChoiceFilterPage(PageParameters parameters) {
        super(parameters);

        // Provider
        data = new ArrayList<Stuff>();
        for (int i = 0; i < 10; i++) {
            data.add(new Stuff(true));
        }
        Provider provider = new Provider();

        // Form
        FilterForm<Stuff> form = new FilterForm<Stuff>("form", provider);
        add(form);

        // Columns
        List<IColumn<Stuff>> columns = new ArrayList<IColumn<Stuff>>();

        IModel<List<? extends Boolean>> choices = new LoadableDetachableModel<List<? extends Boolean>>() {
            @Override
            protected List<Boolean> load() {
                return Arrays.asList(Boolean.TRUE, Boolean.FALSE);
            }
        };
        columns.add(new ChoiceFilteredPropertyColumn<Stuff, Boolean>(Model
                .of("bool"), "boolVal", choices) {

            @Override
            public Component getFilter(String componentId, FilterForm<?> form) {
                ChoiceFilter<Boolean> filter = new ChoiceFilter<Boolean>(
                        componentId, getFilterModel(form), form,
                        getFilterChoices(), enableAutoSubmit()) {

                    @Override
                    protected DropDownChoice<Boolean> newDropDownChoice(
                            String id, IModel<Boolean> model,
                            IModel<List<? extends Boolean>> choices,
                            IChoiceRenderer<Boolean> renderer) {
                        DropDownChoice<Boolean> newDropDownChoice = super
                                .newDropDownChoice(id, model, choices, renderer);
                        newDropDownChoice.setNullValid(true);
                        return newDropDownChoice;
                    }
                };

                IChoiceRenderer<Boolean> renderer = getChoiceRenderer();
                if (renderer != null) {
                    filter.getChoice().setChoiceRenderer(renderer);
                }
                return filter;
            }
        });
        columns.add(new PropertyColumn<Stuff>(Model.of("string"), "stringVal"));

        DataTable<Stuff> table = new DefaultDataTable<Stuff>("table", columns,
                provider, 100);

        // Toolbar
        table.addTopToolbar(new FilterToolbar(table, form, provider));
        form.add(table);
    }

    private class Provider extends SortableDataProvider<Stuff> implements
            IFilterStateLocator<Stuff> {

        private Stuff filter = new Stuff(false);

        public Iterator<? extends Stuff> iterator(int first, int count) {
            if (filter.boolVal == null) {
                return data.subList(first, first + count).iterator();
            } else {
                ArrayList<Stuff> result = new ArrayList<Stuff>();
                for (Stuff stuff : data) {
                    if (filter.boolVal.equals(stuff.boolVal))
                        result.add(stuff);
                }
                return result.subList(first, first + count).iterator();
            }
        }

        public int size() {
            if (filter.boolVal == null) {
                return data.size();
            } else {
                int size = 0;
                for (Stuff stuff : data) {
                    if (stuff.boolVal == filter.boolVal)
                        size++;
                }
                return size;
            }
        }

        public IModel<Stuff> model(Stuff object) {
            return Model.of(object);
        }

        public Stuff getFilterState() {
            return filter;
        }

        public void setFilterState(Stuff state) {
            filter = state;
        }
    }

    private static class Stuff implements IClusterable {

        @SuppressWarnings("unused")
        public String stringVal;
        public Boolean boolVal;

        public Stuff(boolean init) {
            if (init) {
                Random random = new Random();
                stringVal = Integer.toString(random.nextInt());
                switch (random.nextInt(3)) {
                case 0:
                    boolVal = Boolean.FALSE;
                    break;
                case 1:
                    boolVal = Boolean.TRUE;
                    break;
                default:
                    boolVal = null;
                }
            }
        }
    }
}