摘要:[C#]樹狀圖於小視窗傳值的應用
還記得之前有寫過樹狀圖的用法,
想不到過沒幾天又有另一個狀況要用到了,
這次是要在頁面上以開啟小視窗的方式來選擇部門,
點選完畢之後會將選取的部門名稱帶回母視窗,
並且子視窗自動關閉。
先來看一下假想中的組織圖,
相信大家應該都不陌生,
反正就是大的樹狀架構,越往上代表層級越高:
那在資料庫中要怎麼呈現這樣的關係呢?
其實也很簡單,
先用一個欄位紀錄每個階級的代號,(也可以看作是部門代號)
再用另一個欄位去記錄上一層(父層)的代號就好了:
在這個範例中,
將用到兩個頁面,分別是母視窗;以及用來選擇的子視窗:
母視窗:index.aspx
子視窗:tree.aspx
在母視窗中,
先放置一個用來接收訊息的文字方塊,
和用來呼叫子視窗的按鈕:
2 <input type="button" value="選擇" onclick="JavaScript:openTree();" />
然後是用來開啟小視窗的JS碼:
2 {
3 window.open('tree.aspx', 'tree', 'toolbar=no, menubar=no, status=no, scrollbars=no, width=300px, height=400px, resizable=no');
4 }
5 </script>
讀者可以自行設定子視窗大小、是否顯示狀態列等選項,
在此就不贅述。
以上是母視窗要準備的東西,
接下來重點要放在子視窗tree.aspx裡面。
C#程式碼部分:
初始化SQL連接指令:
2 SqlCommand SqlCmd;
3 SqlDataReader MyReader;
然後設定在Page Load時去啟動樹狀圖:
2 {
3 if (!Page.IsPostBack)
4 {
5 addService();
6 }
7 }
樹狀圖部分,先建立父節點:
02 {
03 string nodeName = string.Empty; //節點名稱=部門名稱
04 string nodeValue = string.Empty; //節點值=部門代號
05 //
06 string QryString = "SELECT DeptNo, DeptCName FROM Department WHERE DeptParent IS NULL";
07 SqlConn.Open();
08 SqlCmd = new SqlCommand(QryString, SqlConn);
09 MyReader = SqlCmd.ExecuteReader();
10 while (MyReader.Read())
11 { //先找出最上層的階級(大老闆)
12 nodeName = MyReader ["DeptCName "].ToString();
13 nodeValue = MyReader ["DeptNo "].ToString();
14 }
15 MyReader.Close();
16 SqlConn.Close();
17 //
18 TreeView1.Nodes.Clear();
19 TreeNode MyNode = new TreeNode();
20 MyNode.Expanded = false; //節點是否展開
21 MyNode.Text = nodeName; //節點文字=部門名稱
22 MyNode.Value = nodeValue; //節點值=部門代號
23 MyNode.NavigateUrl = "JavaScript:sendMsg('" + nodeValue + "');"; //目標連結
24 MyNode.Target = ""; //連結開啟方式
25 //
26 MyNode.PopulateOnDemand = true;
27 TreeView1.Nodes.Add(MyNode);
28 }
上面這段程式碼是用來建立最上層階級,(根目錄)
通常也就是董事長、總經理之類的,
其他底下的部門或是副董事長則依附在此階級之下,
形成樹狀圖。
另一個重點就是在於如何把JS的程式放入樹狀圖,並且加上onclick屬性
在一開始時,我很直覺的用TreeView1.Attributes.Add的方式來做,
跑出來的結果卻是無論點哪邊都失敗,
後來才注意到必須將要觸發的JS程式寫在節點的NavigateUrl屬性裡,
這個屬性原本是用來設定點擊節點時要前往的網址,
不過在這邊卻變成了啟動JS程式的onclick屬性,
算是比較特殊的地方。
建立完父節點之後,接下來就要用遞迴的方式去跑出其他子節點,
做法其實跟我之前寫這篇一樣,
[C#]樹狀圖(TreeView)的用法
所以在這邊就只用註解提示,
詳細的運作流程請看之前的文章囉。
2 void PopulateNode(Object sender, TreeNodeEventArgs e)
3 {
4 e.Node.ChildNodes.Clear();
5 PopulateProducts(e.Node);
6 }
02 void PopulateProducts(TreeNode node)
03 {
04 DataSet ResultSet = RunQuery("SELECT DeptNo, DeptCName FROM Department WHERE DeptParent='"+node.Value+"'");
05 //
06 if (ResultSet.Tables.Count > 0)
07 {
08 foreach (DataRow row in ResultSet.Tables[0].Rows)
09 {
10 // 建立新節點
11 //節點參數:(文字, 值, 節點圖片URL, 目標連結URL, 連結開啟方式)
12 TreeNode NewNode = new TreeNode(row["DeptCName"].ToString(), row["DeptNo"].ToString(), "", "JavaScript:sendMsg('" + Convert.ToString(row["DeptNo"]) + "')", "");
13 //
14 // 動態設定 PopulateOnDemand 值,
15 // 在此節點底下仍有子節點時,才會產生展開符號
16 if (chkChildNodes(NewNode))
17 {
18 NewNode.PopulateOnDemand = true;
19 }
20 else
21 {
22 NewNode.PopulateOnDemand = false;
23 }
24 //
25 NewNode.SelectAction = TreeNodeSelectAction.Expand; // 設定點選節點時展開
26 node.ChildNodes.Add(NewNode);
27 }
28 }
29 }
最後,是傳值的JS碼以及HTML code。
2
3 function sendMsg(msgInput)
4 {
5 opener.document.form1.treeMsg.value=msgInput;
6 window.close();
7 }
8 </script>
2 OnTreeNodePopulate="PopulateNode"
3 runat="server" /> </asp:TreeView>
做完感想是這樣做還蠻炫的,
不過馬上被潑了冷水…
「還要跳視窗出來太不人性化了~~~」
「要做在同一個頁面上才方便啊~~~」
…
算了…反正我也不是第一次被打槍…
做這途的真的要有健康的心理啊。