NFace TreeViewer 和ListViewer(JFace Viewer在.Net中的简单实现)

来源:互联网 发布:开淘宝店要交押金吗 编辑:程序博客网 时间:2024/05/16 15:05

  NFace的简单实现

如果您熟悉JFace,那么你最大的感触是什么?优良的设计框架?精简易用的API?简单方便的数据绑定?
以前做基于Eclipse RCP开发的时候,我被JFace的易用和思想吸引,感觉很优雅。JFace中的UI组件十分丰富,功能很多,今天想谈谈如何在.NET中实现其中的一两个组件,也算是我技术BLOG开篇之作。对于.NET中TreeView的DataBinding,我很不喜欢,于是想到模仿JFace TreeViewer的接口写一个.NET版本的NFace TreeViewer,另外将JFace TableViewer实现为NFace ListViewer。但这里只说说TreeViewer的实现,ListViewer的思想是相同的。


一、首先看一下这两个组件的类图,懒得用建模画UML了,下图用VS2005自带的ClassDiagram工具生成:
1.首先是CTreeViewer的类图


1.1       CTreeNode继承于TreeNode类
 

成员
说明
Data
用于存放业务数据(通常是实体类的实例),这样,可以方便的在用户点击树上节点时,取得相应业务数据。
HasGotChildren
是否已经取得过子节点。
IsBlankNode
是否时空节点,空节点是看不到的节点,仅仅用于生成节点上的展开加号,这样,当某个节点未展开时,其下有一个空节点,那么就会形成加号。
NeedRefresh
节点是否需要刷新。
CTreeNode(bool isBlankNode)
用是否空节点构造一个节点
CTreeNode(object obj)
用业务数据构造一个节点
CTreeNode(string text, object obj)
用节点显示文字和业务数据构造一个节点

 
1.2          ITreeViewLabelProvider,CTreeViewer的显示提供器
 

成员
说明
GetImageIndex(object obj)
获取树节点文字前的图像索引号
GetLabel(object obj)
获取树节点显示的字符串
GetSelectedImageIndex(object obj)
获取树节点被选中时文字前的图像索引号

 
1.3          ITreeViewContentProvider,CTreeViewer的内容提供器
 

成员
说明
GetElements()
获根节点对象(可以有多个根节点)
GetElements(object obj)
获取obj节点下的子节点
HasChildren(object obj)
判断obj节点下是否有子节点

 
1.4          CTreeViewer类,继承于TreeView
 

成员
说明
ContentProvider
CTreeViewer的内容提供器
LabelProvider
CTreeViewer的显示提供器
GetChildrenWhenExpand
是否在展开树节点是获取其子节点,该属性影响性能,设置为True时,节点展开时只获取当前层的数据;设置为False时,每次展开一个节点不光获取当前层的数据,也同时获取当前层所有节点的子节点的数据(也就是每次展开一个节点获取两层节点数据)
ExpandToLevel(int)
展开树到指定层
ExpandToLevelByThread(int)
展开树到指定层(线程中完成)
RefreshOnlyOneNode(CTreeNode)
刷新某个节点
OnAfterExpand(TreeViewEventArgs)
重载TreeView的展开后方法,完成获取子节点,构造树的工作
ShowTree()
根据给定的内容提供器和显示提供器,构造显示树内容

 
 
2.然后是NFace ListViewer的类图:


对于CListViewer的类图不再作详细解释,类似CTreeViewer。
 
二、思想
实现IContentProvider和ILabelProvider后,CTreeViewer根据实现该接口的类实例来自动构造一颗树,ContentProvider提供树节点数据(后台业务数据)以及数据之间的关系(父子节点关系),LabelProvider定义如何显示树节点(节点的图标、文字内容)。
 
三、用法
这里举一个简单的例子,将地区信息显示成一颗树。该例中数据从XML读取:
<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  
<District>
    
<ID>0</ID>
    
<Name>中国</Name>
    
<ParentID>-1</ParentID>
    
<IsLeave>false</IsLeave>
  
</District>
  
<District>
    
<ID>1</ID>
    
<Name>美国</Name>
    
<ParentID>-1</ParentID>
    
<IsLeave>false</IsLeave>
  
</District>
  
<District>
    
<ID>2</ID>
    
<Name>日本</Name>
    
<ParentID>-1</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>3</ID>
    
<Name>韩国</Name>
    
<ParentID>-1</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>4</ID>
    
<Name>北京</Name>
    
<ParentID>0</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>5</ID>
    
<Name>上海</Name>
    
<ParentID>0</ParentID>
    
<IsLeave>false</IsLeave>
  
</District>
  
<District>
    
<ID>6</ID>
    
<Name>杭州</Name>
    
<ParentID>0</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>7</ID>
    
<Name>浦东新区</Name>
    
<ParentID>5</ParentID>
    
<IsLeave>false</IsLeave>
  
</District>
  
<District>
    
<ID>8</ID>
    
<Name>徐汇区</Name>
    
<ParentID>5</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>9</ID>
    
<Name>杨浦区</Name>
    
<ParentID>5</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>10</ID>
    
<Name>合庆镇</Name>
    
<ParentID>7</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>11</ID>
    
<Name>张江镇</Name>
    
<ParentID>7</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>12</ID>
    
<Name>川沙镇</Name>
    
<ParentID>7</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
  
<District>
    
<ID>13</ID>
    
<Name>加州</Name>
    
<ParentID>1</ParentID>
    
<IsLeave>true</IsLeave>
  
</District>
</NewDataSet>

简单说明一下:ID是某个地区的ID号,Name是地区名字,ParentID是上级地区的ID号,IsLeave表示是否是叶子地区(其下没有子地区)。

3.1 新建一个WinForm程序,引入IZero.NFace.dll,在窗口上拖放一个CTreeViewer组件,取名为ctv。

3.2 实现一个ContentProvider
class ContentProvider : IZero.NFace.CTreeView.ITreeViewContentProvider 
        
{
            
private DataSet ds;

            
public ContentProvider(DataSet ds)
            
{
                
this.ds =( ds == null ? new DataSet() : ds);  //这里数据集从构造函数传入
            }


            
ITreeViewContentProvider 成员
        }

3.3 实现一个LabelProvider
   class LabelProvider : IZero.NFace.CTreeView.ITreeViewLabelProvider
        
{
            
ITreeViewLabelProvider 成员
        }


3.4 在FormLoad事件里,加载XML文件到一个DataSet,以便待会儿传入ContentProvider,并且对CTreeViewer的内容提供器和显示提供器设置提供器。
 private void FrmTest_Load(object sender, EventArgs e)
        
{          
            DataSet ds 
= new DataSet();
            
try
            
{
                ds.ReadXml(
"TestData.xml");
                
                
this.ctv.ContentProvider = new ContentProvider(ds);
                
this.ctv.LabelProvider = new LabelProvider();
                
this.ctv.GetChildrenWhenExpand = true;  //Default is true
            }

            
catch (Exception err)
            
{
                MessageBox.Show(err.Message);
            }

        }


3.5 在窗口上放一个显示按钮,在其单击事件中,调用CTreeViewer的ShowTree()方法即可。


四、效果图



今天先写到这里,关于CListViewer和CTreeViewer的使用,将会在后续篇幅中用到(可能是一个简单的数据库浏览器)。由于第一次写技术BLOG,经验不足,敬请谅解。


NFace源码和示例程序 下载地址: 目前似乎还不能上传除图片外的资源,不清楚是否支持。如果您想要源码和示例程序,请留下email,我会通过邮件发送。