///如未特別說明,本人所發(fā)表的技術(shù)文章都為原創(chuàng), 任何人引用都請(qǐng)注明出處,并包含本聲明
///作者: csdn網(wǎng)名alias88,郵件:[email protected],qq:63343 歡迎加我 :)
  此樹可以綁定到數(shù)據(jù)源,意味著可隨著綁定管理器同步操作,
  例如position改變自動(dòng)選擇結(jié)點(diǎn),反過來亦然,選擇不同的結(jié)點(diǎn)將改變綁定管理器的position,而且數(shù)據(jù)操作也能同步于綁定管理器,您在datagrid中的改變將即時(shí)反映在樹中......
還有一個(gè)特點(diǎn),對(duì)數(shù)據(jù)結(jié)構(gòu)沒有要求,它總是能正確地將您的數(shù)據(jù)以樹結(jié)構(gòu)展現(xiàn)出來,下圖中,如果使用搜索功能篩選出任一部分?jǐn)?shù)據(jù)出來,左邊的樹形結(jié)構(gòu)也將是正確的
  使用方法和例圖:
  treeview1.allowdrop =true;
  this.treeview1.setdatabinding (this.userdataset ,"會(huì)計(jì)科目"  ,"上級(jí)編號(hào)","科目編號(hào)","科目名稱",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>
  /// 一個(gè)實(shí)現(xiàn)了數(shù)據(jù)綁定的樹
  /// </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 組件設(shè)計(jì)器生成的代碼
    /// <summary> 
    /// 設(shè)計(jì)器支持所需的方法 - 不要使用代碼編輯器 
    /// 修改此方法的內(nèi)容。
    /// </summary>
    private void initializecomponent()
    {
       
      
 
 
    }
    #endregion
 
 
    #region 屬性
    
    /// <summary>
    /// 父節(jié)點(diǎn)
    /// </summary>
    public string parentidcolumn
    {
      get{return parentidcolumn ; }
      set
      {
        if (parentidcolumn!=value  )
        {
          parentidcolumn=value;  
        }
      }
    }
 
 
 
 
    /// <summary>
    /// 子結(jié)點(diǎn)
    /// </summary>
    public string idcolumn
    {
      get{return idcolumn ;}
      set
      {
        if (idcolumn!=value  )
        {
          idcolumn=value;  
        }
      }
    }
 
 
    /// <summary>
    /// 節(jié)點(diǎn)文本
    /// </summary>
    public string textcolumn
    {
      get{return textcolumn ;}
      set
      {
        if (textcolumn!=value  )
        {
          textcolumn=value;  
        }
      }
    }
 
 
    /// <summary>
    /// 樹的根結(jié)點(diǎn)
    /// </summary>
    public object[] topid
    {
      get{return topid ; }
      set
      {
        if (topid!=value  )
        {
          topid=value;  
        }
      }
    }
    
    /// <summary>
    /// 數(shù)據(jù)源
    /// </summary>
    public object datasource
    {
      get{return datasource;}
      set
      {
        object oldsource=this.datasource ;
        if (((value != null) && !(value is ilist)) && !(value is ilistsource))
        {
          throw new exception("該數(shù)據(jù)源不能作為樹的數(shù)據(jù)源!");
        }
        try
        {
          this.setbindingmanager(value, this.datamember , false);
        }
        catch
        {
          this.datasource =oldsource;
        }
      }
    }
 
 
    /// <summary>
    /// 數(shù)據(jù)成員
    /// </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>
    /// 綁定管理器所管理的數(shù)據(jù)列表
    /// </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 綁定管理器的設(shè)置
 
 
    /// <summary>
    /// 設(shè)置綁定
    /// </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 ("參數(shù)設(shè)置錯(cuò)誤,有一個(gè)或多個(gè)列不屬于數(shù)據(jù)源:{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 ("加載表到樹所必需的三個(gè)列中,有一個(gè)或多個(gè)列的類型無效" );
      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 綁定數(shù)據(jù)到樹
 
 
    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>
    /// 將數(shù)據(jù)源綁定到樹
    /// 例子:setdatabinding(mydataset, "部門表","上級(jí)部門編號(hào)","部門編號(hào)","部門名稱",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>
    /// 列出根結(jié)點(diǎn),根結(jié)點(diǎn)為沒有父結(jié)點(diǎn)的結(jié)點(diǎn)
    /// </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是根,無論父是否為空字串,有些算法只將父為空的當(dāng)作根
      }
      if (rootid.count >0)
      {
        object [] result=new object [rootid.count ];
        rootid.copyto (result,0);
        return result;
      }
      return null;
    }
 
 
    
    /// <summary>
    /// 據(jù)數(shù)據(jù)源加入一個(gè)datanode,并加入其所有子樹
    /// </summary>
    /// <param name="pdnode">新datanode的上級(jí)</param>
    /// <param name="datarow">用此行數(shù)據(jù)信息來新建datanode</param>
    internal  void addnodesbydata(updatanode pdnode,object datarow)
    {
      if (datarow==null) return ; 
      updatanode td=buildnewnode(datarow) ;      //不能利用base.addnode()功能,因?yàn)橹荒艿玫疆?dāng)前行
      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()功能,因?yàn)橹荒艿玫疆?dāng)前行
      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:                  //數(shù)據(jù)行增加等要反映到樹節(jié)點(diǎn)上
            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 );        //該行已刪除,在列表已找不到,在此調(diào)用的話會(huì)將刪除行后的當(dāng)前行代表的節(jié)點(diǎn)
            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 ("不能移除節(jié)點(diǎn):" + 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 ("不能移除節(jié)點(diǎn):" + 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>
    /// 節(jié)點(diǎn)加入前的事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void uptreeview_nodeadding(object sender, updatanodeeventargs e)//不論何種增加方法,實(shí)際都在這里處理
    {
      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>
    /// 刪除一個(gè)節(jié)點(diǎn)時(shí)
    /// </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 )            //如果是由于手動(dòng)選擇樹節(jié)點(diǎn)而非由綁定管理器的positinon引起
          {
            int rowindex = this.indexofvalue (this.idproperty ,dnode.key );
            this.bindingmanager.position =rowindex;
          }
        }
      }
      catch
      {
        throw ;
      }
      finally  
      {
 
 
      }
    }
 
 
    #endregion
 
 
    #region 其他方法:取數(shù)據(jù)行,據(jù)數(shù)據(jù)行找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所代表的列的某一個(gè)值位于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 ();  //一定要完全還原,原來沒有排序就不能排序,否則改了排序列數(shù)據(jù)的話,改變類型是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 )            //有下級(jí)又沒有要求取消,否則要處理下級(jí)
      {
        childnode=nodes[0] as updatanode ;                
        while (childnode!=null )          //兄弟節(jié)點(diǎn)可能有多個(gè)
        {
          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
 
 
  }
 
 
  
 
 
}
 
 
中國最大的web開發(fā)資源網(wǎng)站及技術(shù)社區(qū),