覆盖Tapestry的Grid列排序行为

时间:2018-05-08 16:06:24

标签: java tapestry

我有一个使用Grid表的页面,其中可以对一列或多列进行排序。问题是,tapestry似乎按ASCII值排序,这意味着A-Z出现在a-z之前。我希望它被排序,以便A和a在Z和z之前,或者是真正的字母而不是ASCII字母。

我可以在setupRender阶段对值进行正确排序,但问题是用户可以随时单击列标题中的排序图标,列的排序方式将恢复为ASCII方式。

我查看了Grid,GridSortModel和ColumnSort的文档,发现没有什么用于覆盖此行为。我对tapestry非常陌生,但到目前为止文档没有任何帮助,我无法找到另一个在线回答此问题的问题。

我认为我使用的挂毯版本是5.3.6。

谢谢。

编辑:这里有更多背景信息。网格在.tml文件中定义如下:

<table t:type="grid" t:id="productGrid"
model="productModel" source="products" row="product"
                class="product-grid" inPlace="true"
                pagerPosition="both" style="width: 90%"
                include="name,processors,actions" >

然后在java文件中定义产品列表:

@Inject
private IProductConfigurationService _productService;
@Persist
private Set<IProductConfiguration> _products;
. . . .
_products = _productService.getProductConfigurations();

通过修改_products,我可以修改表格/网格的顺序。

1 个答案:

答案 0 :(得分:0)

好的,我终于明白了。 Tapestry对我来说仍然有点神秘,但有一位IRL给了我一个手:

您必须使用自己的类替换默认的GridDataSource类。注意,这段代码可能会被重构,但我现在使用的代码如下所示:

public class MyGridDataSource implements GridDataSource {
    private final List list;

    public MyGridDataSource(final Collection collection) {
        assert collection != null;
        list = CollectionFactory.newList(collection);
    }

    public int getAvailableRows() {
        return list.size();
    }

    public void prepare(int startIndex, int endIndex, List<SortConstraint> sortConstraints) {
        for (SortConstraint constraint : sortConstraints) {
            final ColumnSort sort = constraint.getColumnSort();
            if (sort == ColumnSort.UNSORTED) {
                continue;
            }

            final PropertyConduit conduit = constraint.getPropertyModel().getConduit();

            final Comparator valueComparator = new Comparator<Comparable>() {
                public int compare(Comparable o1, Comparable o2) {
                    if (o1 == null) {
                        return 1;
                    }

                    if (o2 == null) {
                        return -1;
                    }

                    String name1 = (String) o1;
                    String name2 = (String) o2;

                    for (int i = 0; i < Math.min(name1.length(), name2.length()); i++) {
                        Character c1 = name1.charAt(i);
                        Character c2 = name2.charAt(i);
                        Character C1 = Character.toUpperCase(c1);
                        Character C2 = Character.toUpperCase(c2);
                        int diff = 0;

                        // if the letters are different and different case, then....
                        // this allows "a" to come before "Z" for instance
                        if (c1.compareTo(c2) != 0 && C1.compareTo(C2) != 0 && 
                                c1.compareTo(c2) != C1.compareTo(C2)) {
                            diff = C1.compareTo(C2);
                        } else {
                            diff = c1.compareTo(c2);
                        }

                        if (diff != 0) {
                            return diff;
                        }
                    }

                    // shorter strings come first
                    return name1.length() - name2.length();
                }
            };

            final Comparator rowComparator = new Comparator() {
                public int compare(Object row1, Object row2) {
                    Comparable value1 = (Comparable) conduit.get(row1);
                    Comparable value2 = (Comparable) conduit.get(row2);

                    return valueComparator.compare(value1, value2);
                }
            };

            final Comparator reverseComparator = new Comparator() {
                public int compare(Object o1, Object o2) {
                    int modifier = sort == ColumnSort.ASCENDING ? 1 : -1;
                    return modifier * rowComparator.compare(o1, o2);
                }
            };

            Collections.sort(list, reverseComparator);
        }
    }

    public Class getRowType() {
        return list.isEmpty() ? null : list.get(0).getClass();
    }

    public Object getRowValue(int index) {
        return list.get(index);
    }

    public List getList() {
        return list;
    }
}

好的,那么你只需使用这个类作为数据的类型。 (显然,如果你没有指定一个,那么tapestry会自动用DefaultGridDataSource包装你的网格数据。)

这意味着上面的代码只是改为:

@Inject
private IProductConfigurationService _productService;
@Persist
private MyGridDataSource _products;
. . . .
_products = new MyGridDataSource(productService.getProductConfigurations());

这是覆盖默认排序行为的一种方法。可能应该比这更容易。但它确实有效。

相关问题