///如未特别说明,本人所发表的技术文章都为原创, 任何人引用都请注明出处,并包含本声明
///作者: csdn网名alias88,邮件:alias88@163.com,qq:63343 欢迎加我 🙂
此树可以绑定到数据源,意味着可随着绑定管理器同步操作,
例如position改变自动选择结点,反过来亦然,选择不同的结点将改变绑定管理器的position,而且数据操作也能同步于绑定管理器,您在datagrid中的改变将即时反映在树中……
还有一个特点,对数据结构没有要求,它总是能正确地将您的数据以树结构展现出来,下图中,如果使用搜索功能筛选出任一部分数据出来,左边的树形结构也将是正确的
使用方法和例图:
treeview1.allowdrop =true;
this.treeview1.setdatabinding (this.userdataset ,”会计科目” ,”上级编号”,”科目编号”,”科目名称”,null);
using system;
using system.collections;
using system.componentmodel;
using system.drawing;
using system.data;
using system.windows.forms;
using uplibrary.upcommon ;
using uplibrary.upreflect;
using uplibrary.upcontrols ;
using system.diagnostics;
using upsystem.updata ;
namespace upsystem.upcontrols
{
/// <summary>
/// 一个实现了数据绑定的树
/// </summary>
public class uptreeview : uptreeviewbase
{
private object datasource;
private string datamember;
private string parentidcolumn,idcolumn,textcolumn;
private object[] topid=null;
private propertydescriptorcollection propertys=null;
private propertydescriptor parentidproperty,idproperty,textproperty;
private currencymanager bindingmanager=null;
private ibindinglist bindinglist=null;
private bool datasourceevent,treeviewevent;
private dataview dataview=null;
private upsystem.upcommon.upstack stack=new upsystem.upcommon.upstack ();
private system.componentmodel.container components = null;
public event system.eventhandler datasourcechanged;
private system.windows.forms.contextmenu cntmenu;
public uptreeview()
{
initializecomponent();
this.cntmenu = new system.windows.forms.contextmenu();
menuitem mnu;
mnu=cntmenu.menuitems.add (“&o展开”);
mnu.click +=new eventhandler(mnu_click);
mnu=cntmenu.menuitems.add (“&c折叠”);
mnu.click +=new eventhandler(mnu_click);
mnu=cntmenu.menuitems.add (“-“);
mnu=cntmenu.menuitems.add (“&e全部展开”);
mnu.click +=new eventhandler(mnu_click);
mnu=cntmenu.menuitems.add (“&a全部折叠”);
mnu.click +=new eventhandler(mnu_click);
this.contextmenu = this.cntmenu;
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.dispose();
}
}
base.dispose( disposing );
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 – 不要使用代码编辑器
/// 修改此方法的内容。
/// </summary>
private void initializecomponent()
{
}
#endregion
#region 属性
/// <summary>
/// 父节点
/// </summary>
public string parentidcolumn
{
get{return parentidcolumn ; }
set
{
if (parentidcolumn!=value )
{
parentidcolumn=value;
}
}
}
/// <summary>
/// 子结点
/// </summary>
public string idcolumn
{
get{return idcolumn ;}
set
{
if (idcolumn!=value )
{
idcolumn=value;
}
}
}
/// <summary>
/// 节点文本
/// </summary>
public string textcolumn
{
get{return textcolumn ;}
set
{
if (textcolumn!=value )
{
textcolumn=value;
}
}
}
/// <summary>
/// 树的根结点
/// </summary>
public object[] topid
{
get{return topid ; }
set
{
if (topid!=value )
{
topid=value;
}
}
}
/// <summary>
/// 数据源
/// </summary>
public object datasource
{
get{return datasource;}
set
{
object oldsource=this.datasource ;
if (((value != null) && !(value is ilist)) && !(value is ilistsource))
{
throw new exception(“该数据源不能作为树的数据源!”);
}
try
{
this.setbindingmanager(value, this.datamember , false);
}
catch
{
this.datasource =oldsource;
}
}
}
/// <summary>
/// 数据成员
/// </summary>
[defaultvalue((string) null)]
public string datamember
{
get{return datamember;}
set
{
string olddatamember = this.datamember;
try
{
this.setbindingmanager(this.datasource , value , false);
}
catch (exception)
{
this.datamember = olddatamember;
}
}
}
/// <summary>
/// 绑定管理器
/// </summary>
protected currencymanager bindingmanager
{
get
{
return this.bindingmanager;
}
}
/// <summary>
/// 绑定管理器所管理的数据列表
/// </summary>
protected ibindinglist bindinglist
{
get{return bindinglist;}
set
{
setdatasourceevent(false);
this.bindinglist=value;
if (this.bindinglist is dataview )
dataview=(this.bindinglist as dataview );
setdatasourceevent(true);
}
}
protected propertydescriptorcollection propertydescriptors
{
get{return propertys; }
}
private propertydescriptorcollection propertys
{
set
{
propertys=value;
if (propertys!=null)
{
idproperty =propertys.find (this.idcolumn ,true);
parentidproperty=propertys.find (this.parentidcolumn ,true);
textproperty =propertys.find (this.textcolumn ,true);
}
else
{
idproperty=null;
parentidproperty=null;
textproperty=null;
}
}
}
protected propertydescriptor idproperty
{
get{ return this.idproperty ;}
}
protected propertydescriptor parentidproperty
{
get{ return parentidproperty ;}
}
protected propertydescriptor textproperty
{
get{ return textproperty ;}
}
#endregion
#region 绑定管理器的设置
/// <summary>
/// 设置绑定
/// </summary>
/// <param name=”newdatasource”></param>
/// <param name=”newdatamember”></param>
/// <param name=”force”></param>
internal void setbindingmanager(object newdatasource, string newdatamember, bool force)
{
bool datasourcechanged = this.datasource != newdatasource;
bool datamemberchanged = this.datamember !=null && !this.datamember.equals(newdatamember);
if (force || datasourcechanged || datamemberchanged)
{
if (this.datasource is icomponent)
{
((icomponent) this.datasource).disposed -= new eventhandler(this.datasourcedisposed);
}
this.datasource = newdatasource;
this.datamember = newdatamember;
propertys=null;
bindinglist=null;
if (this.datasource is icomponent)
{
((icomponent) this.datasource).disposed += new eventhandler(this.datasourcedisposed);
}
currencymanager manager = null;
if (((newdatasource != null) && (this.bindingcontext != null)) && (newdatasource != convert.dbnull))
{
manager = (currencymanager) this.bindingcontext[newdatasource, newdatamember];
}
if (this.bindingmanager != manager || force)
{
setdatasourceevent(false);
this.bindingmanager = manager;
propertys=this.bindingmanager.getitemproperties ();
if (bindingmanager.list is ibindinglist )
bindinglist=this.bindingmanager.list as ibindinglist ;
setdatasourceevent(true);
}
if (this.bindingmanager != null)
{
this.bindingmanager_itemchanged(this.bindingmanager, null);
}
}
if (datasourcechanged)
{
this.ondatasourcechanged(eventargs.empty);
}
}
protected void ondatasourcechanged(system.eventargs e)
{
if (datasourcechanged!=null)
datasourcechanged(this,e);
}
protected void datasourcedisposed(object sender, eventargs e)
{
this.setbindingmanager(null, “”, true);
}
#endregion
#region 可否绑定的检查
/// <summary>
/// 可否绑定的检查
/// </summary>
internal void checkcolumnindatamanager()
{
if (this.bindingmanager == null)
return ;
propertydescriptor idpd,pidpd,txtpd;
propertydescriptorcollection pds = this.bindingmanager.getitemproperties();
idpd=pds.find (this.idcolumn , true);
pidpd=pds.find (this.parentidcolumn , true);
txtpd=pds.find (this.textcolumn , true) ;
if (idpd==null || pidpd==null || txtpd==null)
throw new argumentexception(string.format (“参数设置错误,有一个或多个列不属于数据源:{0},{1},{2}” ,
this.idcolumn , this.parentidcolumn , this.textcolumn ), “newdatamember”);
// if(!typeof(ilist).isassignablefrom(idpd.propertytype)
// || !typeof(ilist).isassignablefrom(pidpd.propertytype)
// || !typeof(ilist).isassignablefrom(txtpd.propertytype))
// throw new exception (“加载表到树所必需的三个列中,有一个或多个列的类型无效” );
return ;
}
internal bool checkbeforesetbinding()
{
if ( parentidcolumn==null|| idcolumn==null || textcolumn==null ) return false;
if ( parentidcolumn==string.empty|| idcolumn==string.empty || textcolumn==string.empty ) return false;
checkcolumnindatamanager();
if (this.bindingmanager ==null || this.bindinglist ==null) return false;
if (this.bindingmanager.list is dataview )
{
datatable dt =(this.bindingmanager.list as dataview ).table ;
if (dt.columns[this.idcolumn].unique ==false)
throw new exception (string.format (“{0}列不具备唯一性!”,dt.columns [this.idcolumn].caption));
}
return true;
}
#endregion
#region 绑定数据到树
public void setdatabinding ( object datasource, string datamember)
{
this.datamember =datamember;
this.datasource =datasource;
setdatabinding();
}
public void setdatabinding ( object datasource, string datamember,string parentidcol,string idcol,string textcol)
{
this.parentidcolumn =parentidcol;
this.idcolumn =idcol;
this.textcolumn =textcol;
setdatabinding( datasource, datamember);
}
/// <summary>
/// 将数据源绑定到树
/// 例子:setdatabinding(mydataset, “部门表”,”上级部门编号”,”部门编号”,”部门名称”,new object[]{“office”})
/// </summary>
public void setdatabinding ( object datasource, string datamember,string parentidcol,string idcol,string textcol,object[] topid)
{
this.topid =topid;
setdatabinding( datasource, datamember,parentidcol,idcol,textcol);
}
public void setdatabinding()
{
this.hideselection =false;
this.nodes.clear() ;
try
{
settreeevent(false);
setdatasourceevent(false);
if (!checkbeforesetbinding()) return ;
this.beginupdate ();
if (topid==null)
topid=getrootid();
if (topid!=null)
{
object[] drs=this.getitems ( this.idproperty ,topid );
if (drs!=null)
for(int i =0 ; i < drs.length ; i ++ )
addnodesbydata(null,drs[i]);
}
}
catch
{
throw ;
}
finally
{
stack.clear ();
this.endupdate ();
settreeevent(true);
setdatasourceevent(true);
}
}
/// <summary>
/// 列出根结点,根结点为没有父结点的结点
/// </summary>
/// <returns></returns>
internal object [] getrootid()
{
system.collections.arraylist rootid=new arraylist ();
for (int i = 0 ; i < this.bindinglist.count ; i ++)
{
object pkey= this.parentidproperty.getvalue(this.bindinglist[i]);
object key= this.idproperty.getvalue(this.bindinglist[i]);
if (this.indexofvalue (this.idproperty ,pkey )==-1)
rootid.add (key ); //此idcolumn的父不存在,所以此idcolumn是根,无论父是否为空字串,有些算法只将父为空的当作根
}
if (rootid.count >0)
{
object [] result=new object [rootid.count ];
rootid.copyto (result,0);
return result;
}
return null;
}
/// <summary>
/// 据数据源加入一个datanode,并加入其所有子树
/// </summary>
/// <param name=”pdnode”>新datanode的上级</param>
/// <param name=”datarow”>用此行数据信息来新建datanode</param>
internal void addnodesbydata(updatanode pdnode,object datarow)
{
if (datarow==null) return ;
updatanode td=buildnewnode(datarow) ; //不能利用base.addnode()功能,因为只能得到当前行
if (base.addnode (pdnode,td))
{
object[] drvs=this.getitems (this.parentidproperty ,td.key );
if (drvs!=null)
foreach (object drv in drvs)
addnodesbydata(td,drv);
}
}
internal updatanode buildnewnode(object datarow)
{
object key=this.idproperty.getvalue (datarow); //不能利用base.addnode()功能,因为只能得到当前行
if (key==null) return null;
object pkey=parentidproperty.getvalue(datarow);
object text=textproperty.getvalue(datarow);
updatanode td= new updatanode (key,text.tostring ());
return td;
}
internal updatanode buildnewnode(datarow datarow)
{
object key=datarow[this.idcolumn ];
if (key==null) return null;
object pkey=datarow[this.parentidcolumn ];
object text=datarow[this.textcolumn ];
updatanode td= new updatanode (key,text.tostring ());
return td;
}
#endregion
#region 绑定管理器的事件
internal void setdatasourceevent(bool on)
{
if (!on || (on && datasourceevent)) //如果要求去掉事件,或者要求加上事件但先前已加上事件
{
datasourceevent=false;
if (this.bindingmanager!=null)
{
this.bindingmanager.itemchanged -= new itemchangedeventhandler(this.bindingmanager_itemchanged);
this.bindingmanager.positionchanged -= new eventhandler(this.bindingmanager_positionchanged);
}
if (dataview!=null)
{
dataview.table.rowdeleting -=new datarowchangeeventhandler(table_rowdeleting);
dataview.table.rowdeleted -=new datarowchangeeventhandler(table_rowdeleted);
dataview.table.columnchanging -=new datacolumnchangeeventhandler(table_columnchanging);
dataview.table.columnchanged -=new datacolumnchangeeventhandler(table_columnchanged);
dataview.table.rowchanging -=new datarowchangeeventhandler(table_rowchanging);
dataview.table.rowchanged -=new datarowchangeeventhandler(table_rowchanged);
}
else if (this.bindinglist!=null)
this.bindinglist.listchanged -=new listchangedeventhandler(bindinglist_listchanged);
}
if (on )
{
datasourceevent=true;
if (this.bindingmanager!=null)
{
this.bindingmanager.itemchanged += new itemchangedeventhandler(this.bindingmanager_itemchanged);
this.bindingmanager.positionchanged +=new eventhandler(bindingmanager_positionchanged);
}
if (dataview!=null)
{
dataview.table.rowdeleting +=new datarowchangeeventhandler(table_rowdeleting);
dataview.table.rowdeleted +=new datarowchangeeventhandler(table_rowdeleted);
dataview.table.columnchanging +=new datacolumnchangeeventhandler(table_columnchanging);
dataview.table.columnchanged +=new datacolumnchangeeventhandler(table_columnchanged);
dataview.table.rowchanging +=new datarowchangeeventhandler(table_rowchanging);
dataview.table.rowchanged +=new datarowchangeeventhandler(table_rowchanged);
}
else if (this.bindinglist!=null)
this.bindinglist.listchanged +=new listchangedeventhandler(bindinglist_listchanged);
}
}
private void bindingmanager_positionchanged(object sender, eventargs e)
{
try
{
this.afterselect -=new treevieweventhandler(uptreeview_afterselect);
if (this.bindingmanager.position ==-1)
this.selectednode =null;
else
{
object key=this.getvaluebyindex (this.idproperty ,this.bindingmanager.position );
this.selectednode =this.findnode (null, key );
}
}
catch
{
throw ;
}
finally
{
this.afterselect +=new treevieweventhandler(uptreeview_afterselect);
}
}
private void bindingmanager_itemchanged(object sender, itemchangedeventargs e)
{
}
private void bindingmanager_metadatachanged(object sender, eventargs e)
{
}
private void bindinglist_listchanged(object sender, listchangedeventargs e)
{
try
{
stack.push (“bybinding”);
setdatasourceevent(false);
int index=this.bindingmanager.position ;
switch (e.listchangedtype )
{
case listchangedtype.itemadded: //数据行增加等要反映到树节点上
if (this.bindinglist [e.newindex ] is datarowview)
if (!(this.bindinglist [e.newindex ] as datarowview ).isnew )
addnewnodebynewrow(index );
break;
case listchangedtype.itemchanged :
changenodebyrowchanged (index );
break;
case listchangedtype.itemdeleted :
//deletenodebyrowdelete(index ); //该行已删除,在列表已找不到,在此调用的话会将删除行后的当前行代表的节点
break;
case listchangedtype.itemmoved :
//deletenodebyrowdelete(index );
break;
case listchangedtype.reset :
this.allowmovenode =this.bindinglist.allowedit ;
this.allowcopynode =this.bindinglist.allownew ;
break;
}
}
catch(system.exception ex)
{
upsystem.upcommon.upapp.haveerr (this,ex,3);
throw ex;
}
finally
{
setdatasourceevent(true);
stack.pop ();
}
}
private void table_columnchanging(object sender, datacolumnchangeeventargs e)
{
}
private void table_columnchanged(object sender, datacolumnchangeeventargs e)
{
}
private void table_rowchanging(object sender, datarowchangeeventargs e)
{
try
{
stack.push (“bybinding”);
setdatasourceevent(false);
if (e.action ==datarowaction.add )
addnewnodebynewrow(e.row );
else if (e.action ==datarowaction.change )
changenodebyrowchanged(e.row ,datarowversion.default );
else if (e.action ==datarowaction.delete )
deletenodebyrowdelete(e.row );
else if (e.action ==datarowaction.commit )
{
}
else if (e.action ==datarowaction.rollback )
{
if (e.row.rowstate ==datarowstate.added )
deletenodebyrowdelete(e.row );
else if (e.row.rowstate ==datarowstate.modified )
changenodebyrowchanged(e.row ,datarowversion.original );
else if (e.row.rowstate ==datarowstate.deleted )
addnewnodebynewrow(e.row );
}
}
catch
{
throw ;
}
finally
{
setdatasourceevent(true);
stack.pop ();
}
}
private void table_rowchanged(object sender, datarowchangeeventargs e)
{
}
private void table_rowdeleting(object sender, datarowchangeeventargs e)
{
try
{
stack.push (“bybinding”);
setdatasourceevent(false);
deletenodebyrowdelete(e.row );
}
catch
{
throw ;
}
finally
{
setdatasourceevent(true);
stack.pop ();
}
}
private void table_rowdeleted(object sender, datarowchangeeventargs e)
{
}
#endregion
#region 绑定管理器事件的处理
private updatanode addnewnodebynewrow(int rowindex)
{
if ( rowindex<0) return null ;
updatanode node=this.buildnewnode (this.bindinglist[rowindex]);
object pkey=this.getvaluebyindex (this.parentidproperty ,rowindex);
updatanode pnode=this.findnode (null,pkey);
if (base.addnode (pnode,node))
{
return node;
}
return null;
}
private updatanode addnewnodebynewrow(datarow row)
{
if ( row==null) return null ;
updatanode node=this.buildnewnode (row);
object pkey=row[this.parentidcolumn ];
updatanode pnode=this.findnode (null,pkey);
if (base.addnode (pnode,node))
{
return node;
}
return null;
}
private void deletenodebyrowdelete(int rowindex)
{
if ( rowindex<0) return ;
object key=this.getvaluebyindex (this.idproperty ,rowindex);
object text = this.getvaluebyindex (this.textproperty ,rowindex);
updatanode node=this.findnode (null,key);
if (!base.deletenode (node))
throw new exception (“不能移除节点:” + text==null?”无”:text.tostring ());
}
private void deletenodebyrowdelete(datarow row)
{
object key=row [this.idcolumn ];
string text=row [this.idcolumn ].tostring ();
updatanode node=this.findnode (null,key);
if (!base.deletenode (node))
throw new exception (“不能移除节点:” + text==””?”无”:text);
}
private void changenodebyrowchanged(int rowindex)
{
if ( rowindex<0 ) return ;
object key=this.getvaluebyindex (this.idproperty ,rowindex);
updatanode node=this.findnode (null,key);
if (node!=null)
{
node.key =key ;
object text = this.getvaluebyindex (this.textproperty ,rowindex);
if (text !=null && !text.tostring ().equals (“”))
node.text=text.tostring ();
else
node.text=”无”;
object pkey = this.getvaluebyindex (this.parentidproperty ,rowindex);
updatanode pnode=this.findnode (null,pkey);
if (pnode==null && node.parent ==null)
return ;
else
{
updatanode.checknodeaddchild(pnode ,node);
removenode(node);
if (pnode!=null )
pnode.nodes.add (node);
else
this.nodes.add (node);
}
}
}
private void changenodebyrowchanged(datarow row,datarowversion rowversion)
{
if ( row==null ) return ;
object key=row[this.idcolumn ,rowversion];
updatanode node=this.findnode (null,key);
if (node!=null)
{
node.key =key ;
object text = row[this.textcolumn,rowversion ];
if (text !=null && !text.tostring ().equals (“”))
node.text=text.tostring ();
else
node.text=”无”;
object pkey = row[this.parentidcolumn ,rowversion];
updatanode pnode=this.findnode (null,pkey);
if (pnode==null && node.parent ==null)
return ;
else
{
updatanode.checknodeaddchild(pnode ,node);
removenode(node);
if (pnode!=null )
pnode.nodes.add (node);
else
this.nodes.add (node);
}
}
}
#endregion
#region 树的事件
private void settreeevent(bool on)
{
if (!on ||( on && treeviewevent))
{
treeviewevent=false;
this.nodeadding -=new uplibrary.upcontrols.uptreeviewbase.nodeaddhandler(uptreeview_nodeadding);
this.nodedeleting -=new uplibrary.upcontrols.uptreeviewbase.nodedeletehandler(uptreeview_nodedeleting);
this.afterselect -=new treevieweventhandler(uptreeview_afterselect);
}
if (on)
{
treeviewevent=true;
this.nodeadding +=new uplibrary.upcontrols.uptreeviewbase.nodeaddhandler(uptreeview_nodeadding);
this.nodedeleting +=new uplibrary.upcontrols.uptreeviewbase.nodedeletehandler(uptreeview_nodedeleting);
this.afterselect +=new treevieweventhandler(uptreeview_afterselect);
}
}
/// <summary>
/// 节点加入前的事件
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void uptreeview_nodeadding(object sender, updatanodeeventargs e)//不论何种增加方法,实际都在这里处理
{
bool success=false;
try
{
if( sender is updatanode )
success=addnodeevent((updatanode)sender,e.node );
else
success=addnodeevent(null,e.node );
e.cancel =!success;
}
catch
{
throw ;
}
finally
{
}
}
/// <summary>
/// 删除一个节点时
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void uptreeview_nodedeleting(object sender, updatanodeeventargs e)
{
try
{
e.cancel =!deletenodeevent(e.node );
}
catch
{
throw ;
}
finally
{
}
}
private bool addnodeevent(updatanode parentnode,updatanode node)
{
if ( this.bindinglist!=null && !stack.contains (“bybinding”))
{
object newrow=this.bindinglist.addnew ();
if (parentnode!=null)
this.parentidproperty.setvalue (newrow,parentnode.key );
else
this.parentidproperty.setvalue (newrow,dbnull.value );
}
return true;
}
private bool deletenodeevent(updatanode node)
{
if ( this.bindinglist!=null && !stack.contains (“bybinding”))
{
updatanode dnode=node as updatanode;
int rowindex=this.indexofvalue (this.idproperty ,dnode.key );
if (rowindex>=0)
this.bindinglist.removeat (rowindex);
}
return true;
}
private void uptreeview_afterselect(object sender, treevieweventargs e)
{
try
{
if(stack.contains (“bybinding”)) return ;
if (this.selectednode !=null && this.selectednode is updatanode )
{
updatanode dnode=this.selectednode as updatanode ;
if ( dnode!=null ) //如果是由于手动选择树节点而非由绑定管理器的positinon引起
{
int rowindex = this.indexofvalue (this.idproperty ,dnode.key );
this.bindingmanager.position =rowindex;
}
}
}
catch
{
throw ;
}
finally
{
}
}
#endregion
#region 其他方法:取数据行,据数据行找node, 取值
internal propertydescriptor getproperty( string name)
{
return propertys.find (name , true);
}
/// <summary>
/// 获得指定列的属性说明器
/// </summary>
internal propertydescriptor getproperty( string name,bool ignorecase)
{
return propertys.find (name , ignorecase);
}
/// <summary>
/// 获得property所代表的列的某一个值位于bindinglist中的索引
/// </summary>
internal int indexofvalue(propertydescriptor property, object value)
{
if (value == null)
return -1;
if (property == null)
throw new argumentnullexception(“property”);
if (property != null && this.bindinglist !=null && this.bindinglist.supportssearching)
return bindinglist.find(property, value);
for (int i = 0; i < bindinglist.count; i++)
{
object val = property.getvalue(bindinglist[i]);
if (value.equals(val))
return i;
}
return -1;
}
/// <summary>
/// 获得property所代表的列在指定行的值
/// </summary>
protected object getvaluebyindex(propertydescriptor property,int rowindex)
{
if (property==null || this.bindinglist.count <=0 || rowindex<0) return null;
return property.getvalue(this.bindinglist[rowindex]);
}
/// <summary>
/// 获得具有指定值的一行
/// </summary>
internal object getitem(propertydescriptor property, object value)
{
int rowindex=indexofvalue(property ,value);
if (rowindex>=0)
return this.bindinglist[rowindex];
return null;
}
/// <summary>
/// 查找具有指定value的所有行并返回
/// </summary>
internal object[] getitems(propertydescriptor property, object value)
{
if (value == null)
return null;
if (property == null)
throw new argumentnullexception(“property”);
object[] result=null;
arraylist list=new arraylist ();
int index=0;
propertydescriptor oldsort=null;
listsortdirection olddirec=listsortdirection.ascending ;
if (this.bindinglist.supportssorting)
{
oldsort=bindinglist.sortproperty ;
olddirec=bindinglist.sortdirection ;
this.bindinglist.applysort(property,listsortdirection.ascending );
if (bindinglist.supportssearching)
index=bindinglist.find(property, value);
}
while (index>-1 && index<bindinglist.count )
{
object item=bindinglist[index];
object val = property.getvalue(item);
index++;
if (value.equals (val))
list.add (item);
else if (oldsort!=null )
index=-1;
}
if (oldsort!=null)
bindinglist.applysort(property,olddirec );
else
bindinglist.removesort (); //一定要完全还原,原来没有排序就不能排序,否则改了排序列数据的话,改变类型是itemmoved,而不是itemchanged
if (list.count >0)
{
result=new object [list.count ];
list.copyto (result,0);
}
return result;
}
/// <summary>
/// 查找具有指定value的所有行并返回
/// </summary>
internal object[] getitems(propertydescriptor property, object[] values)
{
if (values == null )
return null;
if (property == null)
throw new argumentnullexception(“property”);
object[] result=null,results=null;
arraylist list=new arraylist ();
for(int i=0 ; i < values.length ; i ++)
{
result=getitems(property,values[i]);
if (result!=null)
for(int j=0 ; j < result.length ; j ++)
list.add (result[j]);
}
if (list.count >0)
{
results=new object [list.count ];
list.copyto (results,0);
}
return results;
}
internal updatanode findnode(updatanode topnode,object findkey)
{
updatanode childnode=null,brothernode=null;
treenodecollection nodes;
if (topnode==null )
nodes=this.nodes ;
else
nodes=topnode.nodes ;
if (topnode !=null )
{
updatanode cnode=topnode as updatanode;
if (cnode.key.equals (findkey))
return cnode;
}
if (nodes.count >0 ) //有下级又没有要求取消,否则要处理下级
{
childnode=nodes[0] as updatanode ;
while (childnode!=null ) //兄弟节点可能有多个
{
brothernode=childnode.nextnode as updatanode ;
updatanode result= findnode(childnode,findkey);
if (result!=null )
return result;
else
childnode=brothernode;
}
}
return null;
}
#endregion
#region 树的操作:展开折叠
private void mnu_click(object sender, eventargs e)
{
menuitem mnu=sender as menuitem ;
switch (mnu.index )
{
case 0:
expandall(this.selectednode );
break;
case 1:
if (this.selectednode !=null)
this.selectednode.collapse ();
else
this.collapseall();
break;
case 3:
this.expandall ();
break;
case 4:
this.collapseall ();
break;
}
}
public void expandall(treenode node)
{
if (node!=null)
node.expandall ();
else
base.expandall ();
}
#endregion
}
}