?

樹形結構數據輸入輸出控件的設計與實現

2011-07-25 06:49李俊飛趙衛東
計算機工程與設計 2011年9期
關鍵詞:輸入輸出字段樹形

李俊飛, 陳 皓, 趙衛東

(山東科技大學信息科學與工程學院,山東青島266510)

0 引 言

在現實世界中存在大量的具有樹形關系的數據,譬如設備備件分類、計算機資源管理器、各種社會組織機構等[1]。Windows環境下很多開發工具都提供了一個功能強大的單數據源敏感的樹形控件TreeView,該控件顯示樹形數據清楚且沒有級數限制,輸入輸出數據簡單靈活[2],因此在Windows環境中被普遍應用[3]。但TreeView控件的輸出樹形數據需要大量代碼支持,而且每次TreeView輸出樹形數據都要編寫重復的代碼;TreeView要輸入類似廠家|設備|型號這樣有父級節點的完整信息的數據時實現起來比較困難;采用逐級輸入的方法,上級數據約束下級數據且當樹形數據深度不可預知或不確定時需要編寫大量復雜的代碼,一旦輸入錯誤就要返回出錯位置重新輸入,操作繁瑣且容易產生人為錯誤;此外控件也不支持多數據源輸入輸出。對此,本文在.Net開發平臺下設計并實現了一種樹形結構數據輸入輸出控件來解決以上問題。

1 樹形結構數據輸入輸出控件的整體設計

1.1 樹形結構數據輸入輸出控件的功能要求

樹形結構數據輸入輸出控件是一個數據敏感的樹控件。通過創建幾個屬性,屬性中需要填寫的是與數據庫相關的一些表信息,通過配置這些屬性就可以根據樹形結構數據生成相應的目錄樹。該控件能夠輸入包含所有父節點信息的完整信息。在.Net平臺下TreeView是作為一個獨立的輸出控件使用,輸入需要借助其它控件共同完成,即需要將樹形結構數據輸出控件結合其它控件來共同實現樹形結構數據完整信息的輸入。在整個開發過程中主要使用到3個自定義類:樹形結構數據輸入輸出類、單表樹形結構數據輸出類和多表樹形結構數據輸入輸出類,運用于代碼中分別為ComboTreeView類、DBLeveltreeview類和DBMTtreeview類。

1.2 樹形數據數據庫表結構的設計

樹形結構數據在數據庫表中的存儲主要有兩種方式。一種是單表形式存儲,單表有一個表示樹形結構數據的上下級關系的字段[4],通過本表中一個字段來將上級數據與下級數據關聯在一起。單表結構的好處是樹節點可以無限增加且等級數可以不相同[5];另一種是多表形式存儲,這些表都是按照一定的順序兩兩關聯的且是通過外鍵將樹形結構數據關聯起來,這些數據從第一個表到最后一個表都是一對多的關系,這樣每個表存儲的數據信息單一清晰,表中的信息有明確的意義[6]。以備件編目為例,單表和多表的結構設計分別如圖1和圖2所示。

圖1 備件編目單表結構

圖2 備件編目多表結構

備件編目單表結構中編目編碼是唯一標識備件的字段;編目名稱是樹節點要顯示的文本;所屬上級編目編碼是標識該樹節點父節點的字段;等級即該備件位于整個編目的深度,所處在TreeView中的級數;是否是葉子節點即備件是否還分小的備件,樹節點是否葉子節點;組合名稱是備件的完整名稱,備注記錄備件附加信息。

備件編目多表結構包括備件分類表、備件廠家表、備件類別表和備件型號表4個表。這4個表順次通過分類編碼、廠家編碼和類別編碼相連接,備件分類表中的備件編碼是唯一標識備件分類的字段,分類名稱是樹節點要顯示的分類名稱;備件廠家表的廠家編碼是唯一標識廠家的字段,廠家是樹節點要顯示的廠家名稱;備件類別表的類編編碼是唯一標識類別的字段,類別字段是樹節點要顯示的類別名稱;備件型號表的型號編碼是唯一標識型號的字段,型號字段是樹節點要顯示的型號名稱。

2 樹形結構數據輸出控件的設計

樹形結構數據輸出控件在繼承了 TreeView控件的基礎上,添加一些屬性,這些屬性的設置是填寫數據庫相關表的信息,將TreeView和自定義的方法封裝在控件中,不需要再編寫將樹形結構數據形成樹目錄的代碼[7]。單表和多表樹形結構數據輸出控件的開發是不一樣的,分別如圖3和圖4所示。

圖3 單表樹形結構數據輸出控件類圖

圖4 多表樹形結構數據輸出控件類圖

單表樹形結構數據輸出控件類圖中的DBLeveltree-view類繼承自TreeView類,且調用ImageList類來標注樹節點及樹節點是否選中的狀態。Tablename、DataTableName、DataTableNo、Uppdatatable、Filter、Startupper是DBLeveltreeview類中的自定義屬性,都是字符型的,依次是數據庫表的名稱、樹要顯示的字段、唯一標識表記錄的字段和唯一標識所屬上級節點的字段、樹篩選的條件、0級樹節點所屬上級節點的字段即賦給的一個初始值。這些屬性可以將數據庫表信息傳入DBLeveltreeview控件中,DBLeveltreeview控件根據這些信息將樹形結構數據以樹目錄的形式表示出來,即DBLeveltreeview就是一個數據敏感的自定義樹控件,只需填寫一下數據庫表信息就可以以樹形式顯示樹形結構數據。其中如果沒有篩選條件Filter可以不填,其它屬性必須填寫,不然控件不能正常顯示樹目錄[8]。CreateTree()、AddFunTree()和 DtFunTree()是 DBLeveltreeview 類的方法,依次是創建0級樹節點并調用AddFunTree()方法產生下級樹節點、一個遞歸函數遞歸產生0級以下的樹節點、為創建樹形方法提供datatable。CreateTree()采用的是深度優先遍歷添加樹節點的遞歸算法[9],首先創建樹節點0級節點然后調用AddFunTree()函數,對該節點以下節點遞歸添加[10]。

多表樹形結構數據輸出控件類圖中DBMTTreeview類同樣繼承自TreeView類且調用ImageList類[11]用來標注樹節點及樹節點是否選中的狀態。Tablename、DBTableName、DBTableno、DBForkeyfiel和Filter是DBMTTreeview類的自定義屬性,依次是數據庫表的名稱、樹要顯示的字段、唯一標識表記錄的字段、兩個表之間關聯的外鍵字段和樹篩選的條件。由于要顯示表都要填寫這些屬性,所以這些屬性設置的都是字符數組,且需要按表中數據在樹形結構數據中的級數順次填寫。只有第一個表沒有外鍵可以不填,同樣如果沒有篩選條件Filter可以不填,其它的屬性必須填寫,否則樹目錄不能正常顯示,每個屬性數組的填寫都是用回車隔開的即有多少個表生成的數組長度就為多少。createviewname()是DBMTTreeview類的自定義方法,用來創建三級樹節點即顯示前3個表的表信息,首先判斷屬性數組長度是否小于3,如果小于則成生1級或2級樹,節點完全展開,如果不小于則只展開1級樹節點,第2級和3級的節點都疊加,然后每點擊一級節點生成當前選中樹節點深度加2級的樹節點,3級及以后的樹節點的形成代碼在事件treeView_AfterSelect中,主要算法與createviewname()方法中的算法類似,獲取當前選中節點深度加1與表的個數比較,如果小于且當前選中節點的子節點個數為0則獲取數組為當前節點加1的那組屬性即獲取第當前節點加2個表的信息生成當前節點加1級樹節點否則樹節點已經生成不必執行生成樹節點的代碼。然后判斷當前樹節點深度是否等于表的個數減2,如果等于則不必再執行當前節點加2的樹節點生成代碼,否則執行。每點擊一次樹節點就進行一次判斷,已經生成的樹節點不必再重新生成,這樣可以不用將所有樹形結構數據全部讀出來,減少了讀取數據庫的時間,而且不用在代碼中獲取表的個數,來遞歸生成完整的樹,減少了算法復雜度[12]。

3 樹形結構數據輸入控件的設計

樹形結構數據輸入控件是在樹形結構數據輸出控件基礎上與其它控件相結合來實現的[13]。以ComboBox與單表樹形結構數據輸出控件結合為例,設計的樹形結構數據輸入控件類圖如圖5所示。

ToolStripControlHost、ToolStripDropDown和ComboBox都是.Net中自帶的類,DBLeveltreeview和ComboTreeView是自定義類。自定義類ComboTreeView繼承自ComboBox,由Combo-TreeView類調用DBLeveltreeview類來顯示樹形結構數據。且調用了ToolStripDropDown類和ToolStripControlHost類,Tool-StripControlHost類用來承載 DBLeveltreeview控件,Tool-StripDropDown類是當單擊ComboTreeView控件時用來顯示單表樹形結構數據輸出控件生成的樹目錄[14]。treeView、count和CombinationName是ComboTreeView類的自定義屬性,treeView是調用的DBLeveltreeview類作為ComboTreeView的一個屬性,treeView屬性中包含了DBLeveltreeview類中所有可編輯屬性,當然也包括DBLeveltreeview類的自定義屬性,count是表的個數,CombinationName是數據庫表中顯示組合名稱的字段名稱,方法ComboBoxTreeView()是ComboBoxTreeView控件的構造函數的重載,傳遞參數Tablename,DataTableNo的信息,用于獲取選中節點的組合名稱的信息。

圖5 單表樹形結構數據輸入控件類圖

控件輸入組合名稱的事件是treeView_AfterSelect,觸發事件后顯示組合名稱的核心代碼如下:

if(IsLeaf==true){//判斷是否是葉子節點

this.ValueMember=e.Node.Name;//ComboBox的ValueMember的值是選中樹節點的DataTableNo,即是備件編目編碼

string sql="select"+CombinationName+"from"+Tablename+"where"+DataTableNo+"="+e.Node.Name+"";//獲取選中樹節點的組合名稱

dbOperate.RunSQL(sql,ref ds);

this.Text=ds.Tables[0].Rows[0][0]as string;//ComboBox的文本框中輸入讀取的組合名稱

dropDown.Close();

}

多表樹形結構數據輸入控件的設計與單表類似,就是將圖5中的實體DBLeveltreeview替換為DBMTTreeview。因為表中沒有組合名稱字段,所以方法ComboBoxTreeView()不需要傳遞參數,觸發treeView_AfterSelect事件后顯示組合名稱的核心代碼如下[15]:

if(Count==TreeView.SelectedNode.Level+1){//選中的為葉子節點

for(int i=0;;i++){

if(tn.Parent==null){//節點是否是0級節點

cbtext=tn.Text+"|"+cbtext;

break;//組合名稱賦給字符串以后跳出循環

}

else{

cbtext=tn.Text+"|"+cbtext;//循環讀取樹節點的名稱然后用"|"隔開,賦值給一個字符串

tn=tn.Parent;//將當前節點的父節點賦值給樹節點tn

}

}

cbtext=cbtext.Substring(0,cbtext.Length-1);

this.Text=cbtext;//將組合名稱輸入到文本框中

dropDown.Close();

}

代碼實現的功能是當單擊葉子節點時,獲取葉子節點的完整信息并將完整信息輸入到ComboBox文本框中。葉子節點及其父節點是由“|”依次隔開的,單表組合名稱是存儲在數據庫中的而多表的組合名稱是由葉子節點遍歷其父節點得到的。

4 樹形結構數據輸入輸出控件的實現

樹形結構數據輸入輸出控件跟其它.Net中自帶控件一樣,從工具箱中拖入窗體,配置屬性。以單表樹形結構數據輸入輸出控件為例,將ComboTreeView的連接數據庫的自定義屬性取值添加到窗體初始化控件方法中,控件在窗體內運行時的活動圖如圖6所示。

當DBLeveltreeview控件的屬性 Tablename、DataTable-Name、DataTableNo和Uppdatatable中有一個為null時,就會生成一個沒有任何樹形數據的樹控件 ;當前面屬性都不為null且CombinationName為null時就會生成一個樹形數據正確顯示但關閉不了下拉項而且不能在ComboTreeView文本中顯示組合名稱的控件;當5個屬性都不為null時就會生成一個樹形數據顯示正確,能關閉樹控件且可在ComboTreeView文本中顯示組合名稱的樹形結構數據輸入輸出控件;當選中節點為非葉子節點時,單擊選中節點,雙擊折疊或展開樹節點,選中節點為葉子節點時單擊在ComboTreeView文本中顯示組合名稱,然后關閉樹控件。

動態綁定數據成功運行后生成的樹形結構數據輸入輸出控件如圖7所示。

圖6 樹形結構數據輸入輸出控件活動

圖7 單表樹形結構數據輸入輸出控件生成效果

樹形結構數據輸入輸出控件輸出樹形結構數據信息的形式同原有系統自帶樹形控件一樣,只是不需要再編寫大量生成樹形結構數據的代碼,只需輸入幾個相關的自定義屬性,然后借助ComboBox控件,樹形結構數據輸入輸出控件顯示的樹形結構數據顯示在ComboBox下拉項中,并且可將完整的樹形結構數據信息輸入到ComboBox的文本框。只有葉子節點能被選中填入文本框中,其它節點選中后只能折疊或展開,選中葉子節點后才能將值填入ComboBox的文本框中,輸入的形式為各級節點有“|”隔開,例如上圖的輸入為。這樣樹形結構數據層次清晰,數據之間的關系一目了然,錄入完整信息只需點擊葉子節點,就可以一步到位,不需要根據數據之間的關系逐個錄入。

多表樹形結構數據輸入輸出控件的流程與單表的類似,只是判斷條件略有不同。多表需要判斷各個表的信息是否填寫完整即必須填的屬性是否都按順序填寫好。如果沒有則只生成從第一個表開始屬性填寫完整的樹形結構數據,從不完整的表信息以下所有的樹形結構數據都不顯示;如果第一個表屬性就沒填寫完整則只能生成沒有任何數據的空樹;如果屬性都填寫完整則生成的樹形結構數據輸入輸出控件的效果和圖7是一樣的。

5 結束語

雖然樹形結構數據輸入輸出有很多方式,而且大多數開發平臺也都支持樹形結構數據的輸入輸出,但是它們在實際項目應用中所表現出來的局限性也是顯而易見的。樹形結構數據的輸入輸出通常需要編寫大量的代碼來支持。大量的重復勞動且代碼質量較低,如多數據源樹形結構數據顯示、樹形結構數據完整信息的輸入等問題開發平臺中自帶的控件也很難解決,因此開發解決上述問題一種數據敏感的樹形結構數據輸入輸出控件是非常必要的。本文給出的這套設計創建數據敏感的樹形控件并將樹形控件與其它控件結合來輸入樹形結構數據完整信息的方法,在備件編目的輸入輸出中的到了驗證,取得了很好的效果,并已成功將其運用到視聆公司基站維護管理系統中。

[1]浮光賓,王葵如,張明倫.ASP.NET中TreeView控件的動態綁定及定位展開[J].計算機系統應用,2008,17(6):112-113.

[2]郭兆勝,張登榮.ASP.Net環境下樹狀圖的研究與實現[J].計算機工程與設計,2005,26(2):388-388.

[3]彭彬,劉林,萬小虎.基于.NET的個性化高性能樹形菜單的實現[J].計算機應用與軟件,2009,26(6):138-139.

[4]吉杰,陶培基.MS SQL Server樹形結構表遍歷的循環算法[J].計算機與現代化,2005(4):7-8.

[5]儲岳中.基于遞歸算法和樹形控件的動態樹形圖的實現[J].計算機技術與發展,2007,17(6):88-88.

[6]汪華斌.TreeView在主從表關系處理中的應用[J].計算機與現代化,2006(3):74-75.

[7]姚明,李家蘭.C#開發自定義控件方法探討[J].電腦知識與技術,2007,3(5):798-798.

[8]吳文強.用自定義TreeView控件實現層次結構數據瀏覽功能[J].電腦編程技巧與維護,2010(9):45-46.

[9]王桃群,盧東方.利用TreeView控件動態生成無限級樹[J].儀器儀表用戶,2007,2(14):91-92.

[10]王昕哲,劉萬軍.在Web應用開發中利用靜態樹和遞歸算法制作動態樹型菜單[J].計算機與現代化,2008(3):125-126.

[11]崔曉陽.用TreeView控件實現樹形管理信息系統[J].農業網絡信息,2007(11):135-136.

[12]Khosravi S.The custom TreeView ASP.NET 2.0 server control[J].Software Tools for the Professional Programmer,2005,30(11):64-67.

[13]孫宜貴,王宏勇.NET復合控件在科研業績管理系統中的應用研究[J].計算機與數字工程,2010,38(2):43-45.

[14]劉海鑫.VB.NET中的自定義日期控件開發[J].電腦知識與技術,2007,3(4):1058-1060.

[15]李志華,林財興,謝甘第.TreeView控件在ASP.NET2.0中的應用[J].現代機械,2009(1):70-72.

猜你喜歡
輸入輸出字段樹形
桃樹幾種樹形的特點及整形修剪要點
萊陽茌梨老齡園整形修剪存在問題及樹形改造
Camtasia Studio高清視頻輸入輸出原理及方法
淺談臺灣原版中文圖書的編目經驗
鐵路信號系統安全輸入輸出平臺
獼猴桃樹形培養和修剪技術
休眠季榆葉梅自然開心樹形的整形修剪
輸入輸出理論在大學英語聽說課堂中的教學探索
輸入輸出視角下高職英語教學研究
CNMARC304字段和314字段責任附注方式解析
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合