9

カスタムでGWT 2.1のCellBrowserTreeViewModelを使用しています。次に、TreeViewModel は を使用しAsyncDataProviderてデータを動的にフェッチします。これはすべてうまく機能します。ユーザーがノードをクリックすると、AsyncDataProvider が RPC 経由で結果を取得し、CellBrowser が忠実に結果を表示します。

これを理解できないのはばかげていると思いますが、プログラムでCellBrowserにデータをリロード(および表示)するように指示するにはどうすればよいですか? どうにかしてルート ノードの AsyncDataProvider へのハンドルを取得し、その上で updateRowData() と updateRowCount() を呼び出す必要があると推測していますが、ブラウザー (またはそのモデル) にクエリを実行する明確な方法がわかりません。ルート DataProvider 用。

null 引数を探すコードを AsyncDataProvider コンストラクターに追加できると思います。それにより、「ねえ、私はルートです」と認識し、どこかに参照を保存しますが、それはハックのようです。確かにこれを行うより良い方法があります。

ここに非常に多くのコードをダンプして申し訳ありませんが、これをより単純なものに要約し、十分なコンテキストを提供する方法がわかりません。

私の 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

4 に答える 4

10

多くの人がこれと同じ問題を抱えているようです。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は、アクティビティを介して呼び出すことができます。ただし、コントローラーロジックはセットアップされています。

/**
* 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
于 2011-01-21T08:00:14.910 に答える
7

次のコードは基本的に同じですが、AsyncDataProvider を使用する代わりに HasData インターフェイスからのものです。

HasData<T> display;
...
display.setVisibleRangeAndClearData(display.getVisibleRange(), true);
于 2012-06-28T17:08:14.907 に答える
2

affableblokeの回答が「正しい」とマークされ、多くの賛成票が投じられた理由がわかりません!?

Caffeine Coma は、 Cell TableではなくCell Browserの更新について尋ねましたが、それはまったく別のものです!

私にとっては、次のトリックが機能しました。DataProviderの外側で sを定義し、TreeViewModelそれらを引数としてコンストラクターに渡します。私の場合、最初に空のデータ構造を提供します。

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(...);
于 2013-05-08T10:55:02.907 に答える