達步社群專業網站 達步社群 (Dabutek Community)

RSS

社區設施





快速搜尋
»
進階搜尋» 技術支援官網
   
 

Table of Contents [Hide/Show]


      使用動機
      資料結構
      遞迴函式
      UI設計
      文章結論

作者: Tomex Ou
版本歷史:
2008/05/30 AM 12:26:26 以TreeView控件為例實作無層數限制的項目分類心得。

使用動機

通常,資訊相關科系的程式資料結構課程,一定會教遞迴函式(Recursive Method)呼叫,它的要點是否充份掌握,端視對Recursive要有充份體認及經驗。老實說,遞迴函式雖然精簡優美,但樹系層間的區域變數記憶體卻得等到子串中最後節點return才得到釋放,假如沒有斟酌好整體資料的壓力量,函式因為跑不出來而死當是常見的現象。然而,Parent-Child的資料結構讀取,不用到遞迴函式實在是很難,因此好好面對這樣的程式技巧,是很重要的突破歷程。

資料結構

Parent-Child資料結構常見於樹狀結構(Tree)、層狀選單(Menu)及項目分類(Category), 其中項目分類(Category)是最常見的結構,但我們常常因為便宜行事而固定死層數,等事後想要變數層數或移動某節點位置就得傷透腦筋。我以ASP.NET中的TreeView控件為例(即使是控件Menu也一樣類似,把Nodes改成Items即可),來示範如何設計這樣的結構:
Image

要如何設計這樣的Parent-Child資料結構呢? 其實重點在於ParentId與ItemId兩欄位的指定,例如下圖:
Image

遞迴函式

TreeView控件的節點是採用遞迴函式動態建立的,如下圖:
Image


初學者常常不知道遞迴函式該傳入什麼參數(Parameters),以上圖函式為例,參數#1會使用TreeNodeCollection來代替直覺的父節點(TreeNode)的原因,在於TreeView.Nodes=TreeNode.ChildNodes的統一,能省下第一層節點的浪費舖陳。參數2的DataTable是將整個分類資料一次從資料庫取出,在Client記憶體中過濾選取是比較快速的,另外函式中使用Rows.Select()來替代篩取子資料較快速的DataView.RowFilter之原因,在於遞迴呼叫中DataView.RowFilter被不斷改變而影響上層節點的讀取有關。

UI設計

在使用者介面(UI)中操作樹狀控件,若能透過AJAX技巧減少更新的Callback是較好的考量,但很可惜官方文件指定TreeView, Menu, FileUpload等控制因為使用到Client Script的技術而干擾AJAX運作,因此放入UpdatePanel中是無效的。不過我發現在VS2008+ASP.NET 3.5下,只要把TreeView有關操作Client的屬性設定False,那麼大致上就可以使用AJAX來刷新節動的異動狀況。
Image

文章結論

資料表格及遞迴函式的設計特性,並非一眼瞟過就能熟稔上手,只要用心好好研究這樣的Parent-Child結構及遞迴編程技巧,在系統設計實作上會幫助很大。千萬不要只會拉既成的SqlDataSource或固定格式的XML來餵食TreeView,因為如果你沒完全了解本文的重點,下次遇到還是不會。

參考文獻:
  1. 1 資料表格Shcema主要是參考vBulletin等知名論壇的文章表格,並實作遞迴式版面巡覽路徑程式而大功告成。

ScrewTurn Wiki version 3.0.5.600. Some of the icons created by FamFamFam.