2013-02-18 23 views
6

我有一个GWT单元格树,我用它来显示CMS的文件结构。我正在使用从我创建的自定义RPC类加载数据的AsyncDataProvider。我也有一个网络套接字系统,可以从系统中的其他客户端广播事件(文件创建,重命名,移动,删除等)。如何通过事件总线告诉GWT单元格小部件数据已更改?

我试图包裹我的头是当我收到这些事件之一,我如何正确更新我的细胞树?

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

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

注意:即使它看起来像我是我的自定义RPC框架,我没有使用RequestFactory。此外,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()); 
      } 
     } 
    } 

回答

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); 
     } 
} 
+0

不是我正在寻找的东西,但这是有效的。对于维护索引FileEntity-> TreeNode以改善查找时间,您有什么想法?谢谢! – 2013-02-27 19:05:19

+0

是的,它总是更好地使用索引... – Adarsha 2013-02-28 03:13:40

0

您可以使用数据提供程序来更新celltree。 您可以用更新的完整细胞树:

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

如果您只想更新一个特殊的细胞,你可以从dataProvider中的listwrapper和只设置一个元素。

provider.getList().set(12, element); 
+0

这必须与AsyncDataProvider一起使用,其中新数据来自服务器。我不认为这种方法会起作用... – 2013-02-26 16:17:06

相关问题