6

我有一个 GWT 单元树,用于显示来自 CMS 的文件结构。我正在使用AsyncDataProvider从我创建的自定义 RPC 类加载数据。我还有一个 Web Socket 系统,它将广播来自也在系统中工作的其他客户端的事件(文件创建、重命名、移动、删除等)。

我想要解决的是当我收到这些事件之一时,我如何正确更新我的细胞树?

我想这个问题类似于在页面上有两个我的 Cell Tree 实例,它们呈现相同的服务器端数据,并希望确保当用户更新一个时,另一个也更新,通过使用EventBus.

我觉得这应该很简单,但我现在已经花了大约 6 个小时,没有任何进展。我的代码包括在下面:

注意:我没有使用 RequestFactory,即使它看起来像是我的自定义 RPC 框架。此外, FileEntity 只是一个文件的简单表示,其名称可由getName().

private void drawTree() {

        // fileService is injected earlier on and is my own custom rpc service
        TreeViewModel model = new CustomTreeModel(new FileDataProvider(fileService));
        CellTree tree = new CellTree(model, "Root");

        tree.setAnimationEnabled(true);

        getView().getWorkspace().add(tree);

    }

    private static class CustomTreeModel implements TreeViewModel {

        // I am trying to use a single AsyncDataProvider so I have a single point of loading data which I can manipulate (Not sure if this is the correct way to go)
        public CustomTreeModel(FileDataProvider dataProvider) {
            this.provider = provider;
        }


        public <T> NodeInfo<?> getNodeInfo(final T value) {

            if (!(value instanceof FileEntity)) {

                                // I already have the root File loaded in my presenter, if we are at the root of the tree, I just add it via a list here
                ListDataProvider<FileEntity> dataProvider = new ListDataProvider<FileEntity>();

                dataProvider.getList().add(TreeWorkspacePresenter.rootFolder);

                return new DefaultNodeInfo<FileEntity>(dataProvider,
                        new FileCell());
            } else {

                                // Otherwise I know that we are loading some tree child data, and I invoke the AsyncProvider to load it from the server
                provider.setFocusFile(value);

                return new DefaultNodeInfo<FileEntity>(provider,
                        new FileCell());
            }
        }

        public boolean isLeaf(Object value) {

            if(value == null || value instanceof Folder)
                return false;
            return true;
        }

    }

    public class FileDataProvider extends AsyncDataProvider<FileEntity> {

        private FileEntity focusFile;
        private FileService service; 

        @Inject
        public FileDataProvider(FileService service){
            this.service = service;
        }

        public void setFocusFile(FileEntity focusFile){
            this.focusFile = focusFile;
        }

        @Override
        protected void onRangeChanged(HasData<FileEntity> display) {


                service.getChildren(((Folder) focusFile),
                        new Reciever<List<FileEntity>>() {

                            @Override
                            public void onSuccess(List<FileEntity> files) {

                                updateRowData(0, files);

                            }

                            @Override
                            public void onFailure(Throwable error) {

                                Window.alert(error.toString());
                            }

                        });

            }
        }



    /**
     * The cell used to render Files.
     */
    public static class FileCell extends AbstractCell<FileEntity> {

        private FileEntity file;

        public FileEntity getFile() {
            return file;

        }

        @Override
        public void render(Context context, FileEntity file, SafeHtmlBuilder sb) {
            if (file != null) {
                this.file = file;
                sb.appendEscaped(file.getName());
            }
        }
    }
4

2 回答 2

2

目前,即使在最新的 gwt 版本中,也没有直接支持单个树项刷新。

但是有一个解决方法。每个树项都与一个值相关联。使用此值,您可以获得相应的树项。

在您的情况下,我假设您知道要更新/刷新的项目,即您知道哪个文件实体已更改。使用此文件实体搜索相应的树项。获得树项后,您只需要展开和折叠或折叠并展开其父项。这使得父项重新渲染其子项。您更改的文件实体是子项之一。所以它得到刷新。

public void refreshFileEntity(FileEntity fileEntity)
{
       TreeNode fileEntityNode = getFileEntityNode(fileEntity, cellTree.getRootTreeNode() 

       // For expnad and collapse run this for loop

       for ( int i = 0; i < fileEntityNode.getParent().getChildCount(); i++ )
    {
        if ( !fileEntityNode.getParent().isChildLeaf( i ) )
        {
            fileEntityNode.getParent().setChildOpen( i, true );
        }
    }

}

public TreeNode getFileEntityNode(FileEntity fileEntity, TreeNode treeNode)
{
       if(treeNode.getChildren == null)
       {
           return null;
       }
       for(TreeNode node : treeNode.getChildren())
       {
            if(fileEntity.getId().equals( node.getValue.getId() ))
            {
                 return node;
            }
            getEntityNode(fileEntity, node); 
       }
}
于 2013-02-27T15:16:11.927 回答
0

您可以使用 dataprovider 来更新 celltree。您可以使用以下命令更新完整的单元格树:

provider.setList(pList);
provider.refresh();

如果您只想更新一个特殊的单元格,您可以从 dataprovider 获取 listwrapper 并只设置一个元素。

provider.getList().set(12, element);
于 2013-02-26T08:42:12.510 回答