GWT:如何以编程方式重新加载CellBrowser?

时间:2011-01-15 20:58:42

标签: gwt cellbrowser

我正在使用带有自定义TreeViewModel的GWT 2.1 CellBrowser。 TreeViewModel反过来使用AsyncDataProvider动态获取数据。这一切都很好用 - 当用户点击一个节点时,我的AsyncDataProvider通过RPC获取结果,并且CellBrowser尽职尽责地显示它们。

我觉得无法解决这个问题很愚蠢,但我怎么能以编程方式告诉CellBrowser重新加载(和显示)数据呢?我猜我需要以某种方式为我的根节点获取AsyncDataProvider的句柄,然后调用updateRowData()& updateRowCount()就可以了,但我没有看到一种明显的方法来查询根DataProvider的浏览器(或其模型)。

我想我可以在我的AsyncDataProvider构造函数中添加代码来查找null参数,并通过这种方式识别“嘿,我是根”并在某处存储引用,但这似乎是hackish。当然有更好的方法来做到这一点。

抱歉在这里倾销了如此多的代码,但我不知道如何将其简化为更简单的东西,并且仍能提供足够的上下文。

我的AsyncDataProvider:

private static class CategoryDataProvider extends AsyncDataProvider<Category>
{           
    private Category selectedCategory;

    private CategoryDataProvider(Category selectedCategory)
    {
        this.selectedCategory = selectedCategory;
    }

    @Override
    protected void onRangeChanged(HasData<Category> display)
    {
        new AsyncCall<List<Category>>()
        {
            @Override
            protected void callService(AsyncCallback<List<Category>> cb)
            {
                // default to root
                String categoryId = "-1";
                if (selectedCategory != null)
                {
                    categoryId = selectedCategory.getCategoryId();
                }

                // when a category is clicked, fetch its child categories
                service.getCategoriesForParent(categoryId, cb);
            }

            @Override
            public void onSuccess(List<Category> result)
            {
                // update the display
                updateRowCount(result.size(), true);
                updateRowData(0, result);
            }
        }.go();

    }
}

我的模特:

private static class CategoryTreeModel implements TreeViewModel
{
    private SingleSelectionModel<Category> selectionModel;

    public CategoryTreeModel(SingleSelectionModel<Category> selectionModel)
    {
        this.selectionModel = selectionModel;
    }

    /**
     * @return the NodeInfo that provides the children of the specified category
     */
    public <T> NodeInfo<?> getNodeInfo(T value)
    {
        CategoryDataProvider dataProvider = new CategoryDataProvider((Category) value);

        // Return a node info that pairs the data with a cell.
        return new TreeViewModel.DefaultNodeInfo<Category>(dataProvider, new CategoryCell(), selectionModel, null);
    }

    /**
     * @return true if the specified category represents a leaf node
     */
    public boolean isLeaf(Object value)
    {
        return value != null && ((Category) value).isLeafCategory();
    }
}

最后,我正在使用它们:

        CategoryTreeModel model = new CategoryTreeModel(selectionModel);
        CellBrowser cellBrowser = new CellBrowser(model, null);

4 个答案:

答案 0 :(得分:10)

看起来很多人都有这个same issue。以下是我处理从AsyncDataProvider刷新数据的方法。

首先,创建一个接口,通过包装AsyncDataProvider的受保护onRangeChanged方法来添加刷新数据提供程序的功能。例如......

HasRefresh.java

public interface HasRefresh<HasData<T>>{
  /**
   * Called when a display wants to refresh 
   *
   * @param display the display to refresh
   */
   void refresh(HasData<T> display);

}

然后需要刷新的CellTable可以通过Activity调用它,或者你的控制器逻辑被设置。

/**
* A custom {@link AsyncDataProvider}.
*/
public class MyAsyncDataProvider extends
            AsyncDataProvider<Entity> implements HasRefresh<Entity> {

            public void refresh(Entity display){

                  onRangeChanged(display);
             }

             /**
         * {@link #onRangeChanged(HasData)} is called when the table requests a
         * new range of data. You can push data back to the displays using
         * {@link #updateRowData(int, List)}.
         */
        @Override
        protected void onRangeChanged(
                HasData<Entity> display) {
            currentRange = display.getVisibleRange();
            final int start = currentRange.getStart();

            dataServiceQuery = context.getEntities();

            dataServiceQuery
                    .execute(new DataServiceQueryHandler<Entity>() {

                        @Override
                        public void onQueryResponse(
                                DataServiceQueryResponse<Entity> response) {


                            updateRowCount(response.getCount(), true);
                            updateRowData(start, response.getEntities());

                        }
                    });

        }// end onRangeChanged()

    }// end MyAsyncDataProvider class

答案 1 :(得分:7)

现在发现,以下代码基本相同,但是来自HasData接口,而不是使用AsyncDataProvider。

HasData<T> display;
...
display.setVisibleRangeAndClearData(display.getVisibleRange(), true);

答案 2 :(得分:2)

我不明白为什么affablebloke的回答被标记为“正确”并且被支持了这么多!?

Caffeine Coma询问有关更新 Cell Browser 而不是 Cell Table 的信息,这些是完全不同的事情!

对我来说,以下技巧有效: 我在DataProvider之外定义TreeViewModel s并将它们作为参数传递给构造函数。在我的例子中,他们在开头提供空数据结构。

现在您可以从“outside”引用DataProvider以更新Cell Browser。

示例:

private class MyTreeViewModel implements TreeViewModel {

    AbstractDataProvider<MyDataStructure> myDataProvider;

    public MyTreeViewModel(AbstractDataProvider<MyDataStructure> myDataProvider)
    {
        this.myDataProvider = myDataProvider;
    }

    @Override
    public <T> NodeInfo<?> getNodeInfo(T value) {
        if(value == null)
        {
            // Level 0
            return new DefaultNodeInfo<MyDataStructure>(myDataProvider, new MyCellImpl());
        }
    }
}


AbstractDataProvider<MyDataStructure> myDataProvider = new ListDataProvider<MyDataStructure>(new ArrayList<MyDataStructure>()); // or AsyncDataProvider
MyTreeViewModel myModel = new MyTreeViewModel(myDataProvider);

CellBrowser<MyDataStructure> cellBrowser = new CellBrowser.Builder<MyDataStructure>(myModel, null).build();

/*
  here you can do some stuff, for example, bind the CellBrowser to a template with UiBinder
*/

/*
 if you use a ListDataProvider, do
*/

myDataProvider.setList(myDataStructureFromSomewhere);
myDataProvider.refresh();

/*
 if you use an AsyncDataProvider, do
*/

myDataProvider.updateRowData(..., myDataStructureFromSomewhere);
myDataProvider.updateRowCount(...);

答案 3 :(得分:0)

我遇到了同样的问题,这对我有用:

 List<TreeGridRecord> dataToTable = ....

int firstPosition = this.pager.getDisplay().getVisibleRange().getStart();
this.dataProvider.updateRowData(firstPosition, dataToTable);

int rowCount = this.pager.getPageStart() + dataToTable.size();
this.dataProvider.updateRowCount(rowCount, exactCount);

&#34;寻呼机&#34;是一个控制表分页的SimplePager。

希望这有帮助!