筆記-讓ASP.NET TreeView可以透過Javascript新增節點
2 |
同事在網頁上用了ASP.NET TreeView控件,但專案規格中需要由Javascript端完成新增節點的動作,很不幸地,這不是ASP.NET TreeView內建支援的功能。
如果時間充裕的話,我會建議改用jQuery TreeView Plugin,較符合大量Client端客製的需求,但因時程迫在眉睫,且只差這個小功能,所以大家不要考究"破解"ASP.NET TreeView前端設計的意義,把它想像成打破水缸救人就好。
寫完這段程式,等同於小小地破解ASP.NET TreeView前端HTML與Script設計。發現原來每一個節點都是一個Table(選擇用Table來配置排列而沒用CSS,應是著眼於相容性,至於要相容誰相信大家心裡有數,讓我們一起吶喊"IE6退散"吧!),其下的子節點則被包在一個DIV中。比較複雜的部分是前方的連接線圖示,圖檔是以Web Resource方式存在,所以URL難以預測,幸好有個TreeView1_ImageArray的字串函數記載了所有圖示的URL,可用Index去找出特定圖示。
不過要考慮節點所在位置不同,有時要用L型,有時要用├,有時要補空白,有時要補直線,麻煩的很,這部分花了不少Code處理。
<%@ Page Language="C#" AutoEventWireup="true" %>
<script type="text/C#" runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TreeNode root = new TreeNode("Root");
root.ChildNodes.Add(new TreeNode("Catg1"));
root.ChildNodes.Add(new TreeNode("Catg2"));
TreeNode node = new TreeNode("Catg3");
node.ChildNodes.Add(new TreeNode("ItemX"));
root.ChildNodes.Add(node);
root.ChildNodes.Add(new TreeNode("Catg4"));
SetTreeNodeLink(root);
TreeView1.Nodes.Add(root);
}
}
private void SetTreeNodeLink(TreeNode node)
{
node.NavigateUrl = "javascript:selNode('" + node.Text + "');void(0);";
foreach (TreeNode child in node.ChildNodes)
SetTreeNodeLink(child);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>TreeView Client Script</title>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js?WT.mc_id=DOP-MVP-37580"
type="text/javascript"></script>
<script type="text/javascript">
$(function () {
//選取節點時觸發
window.selNode = function (t) { $("#dvSelNode").text(t); };
$("#btnAdd").click(function () {
//註: 此處不考慮父節點名重覆及txtName特殊字元問題
addNode($("#dvSelNode").text(), $("#txtName").val(),
"javascript:selNode('" + $("#txtName").val() + "');void(0);");
});
var tvName = "TreeView1";
var $tv = $("#" + tvName);
//Icon Url
var tvIcons = window[tvName + "_ImageArray"];
//傳回連接線Icon
function genTreeViewIcon(i) {
return "<img style='border-width: 0px;' src='" +
tvIcons[i] + "' />";
}
//查出連接線Icon的索引值,有時要用相對順序算出展開收合狀態的Icon
function getTreeViewIconIndex(imgUrl) {
for (var i = 0; i < tvIcons.length; i++)
if (tvIcons[i].length > 0 &&
imgUrl.indexOf(tvIcons[i]) > -1) return i;
return -1;
}
//加入新節點
function addNode(parentNodeText, nodeText, nodeLink) {
//先找到Table
var $pt = null;
$tv.find("a").each(function () {
if (this.innerHTML == parentNodeText) {
$pt = $(this).closest("table");
return false;
}
});
if ($pt) {
//找出目前節點的名稱
var nodeId = $pt.find("a:last").attr("id");
var childBlockId = nodeId.replace("t", "n");
//檢查是否已有Child, 若無則加上子節點div
if (!$pt.next().is("div")) {
//找到前方的圖示
var $pfxTd = $pt.find("td").eq(-2);
var imgUrl = $pfxTd.find("img").attr("src");
//Icon索引+2可換算出可展開的Icon
$pfxTd.html(
"<a id='" + childBlockId +
"' href=\"javascript:TreeView_ToggleNode(" + tvName + "_Data," +
nodeId.substr(nodeId.lastIndexOf("t") + 1, 3) + ","
+ childBlockId + ",'t'," + childBlockId + "Nodes)\">" +
genTreeViewIcon(getTreeViewIconIndex(imgUrl) + 2) +
"</a>");
$pt.after("<div id='" + childBlockId + "Nodes' style='display: block' />");
}
var $childBlock = $pt.next();
//計算新Node的流水號
var maxSn = $tv.find("a").length + 1;
var newNodeId = nodeId.substr(0, nodeId.lastIndexOf("t") + 1) + maxSn;
//以自己為複製藍本,重點要多加一格後縮
var $npt = $pt.clone();
//設定節點新值
$npt.find("a:last").attr("id", newNodeId).attr("href", nodeLink).text(nodeText);
//處理連接線
var $cell = $npt.find("td").eq(-2);
var imgUrl = $cell.find("img").attr("src");
var idx = getTreeViewIconIndex(imgUrl);
if (idx >= 11 && idx <= 13) idx = 6; else idx = 3;
$cell.html(genTreeViewIcon(idx)) //改連接線
.after("<td>" + genTreeViewIcon(13) + "</td>");
if ($childBlock.children().length > 0) {
//如果已有其他兄弟節點,要改最後一筆兄弟節點的連接線
var $lastItem = $childBlock.children("table").last();
$cell = $lastItem.find("td").eq(-2);
($cell.children("a").length ? $cell.children("a") : $cell)
.html(genTreeViewIcon(
getTreeViewIconIndex($cell.find("img").attr("src")) - 3));
//若兄弟節點已有子節點也要改其連接線(實在有夠麻煩)
if ($lastItem.next().is("div")) {
var tdIdx = $lastItem.find("td").length - 2;
$lastItem.next().children().each(function () {
$(this).find("td:eq(" + tdIdx + ")").html(
genTreeViewIcon(6) //直線
);
});
}
}
$childBlock.append($npt);
}
}
var h = [];
for (var i = 0; i < TreeView1_ImageArray.length; i++) {
h.push("<span>" + i + genTreeViewIcon(i) + "</span>");
}
$("#dvDisp").html(h.join("\n"));
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div id="dvDisp"></div>
<div>
<div id="dvSelNode">Not Selected</div>
<div>
<input type="text" id="txtName" value="" />
<input type="button" id="btnAdd" value="Add" />
</div>
<asp:TreeView ID="TreeView1" runat="server" Height="250px" ShowLines="True"
Width="320px">
</asp:TreeView>
</div>
</form>
</body>
</html>
以上是程式,我當救人兼練功,各位有興趣隨便看看,沒什麼大用。
Comments
# by 91
要改名叫司馬黑暗了 :D 這水缸好麻煩啊...
# by Ark
不爭氣的笑了