Skip to content

符合标准的TreeView实现(Div+CSS+JS+ASP.NET)

这几天有点小活,要求是ASP.NET的,虽然我不怎么看好ASP.NET,但是人家要求了我也就照做吧。 最复杂的部分是一个TreeView。出于兼容性和简单性考虑没有用ASP.NET的TreeView控件,而是参考一篇文章自行写了一个出来。

技术指标如下:

  • **实现:**Div+CSS+JavaScript+ASP.NET(C#)

  • **功能:**可以实现无限级的TreeNode

  • **标准:**在IE 7和Firefox 3.1下显示效果相同,兼容XHTML 1.0 Strict最严格的网页标准

效果如左图所示。最后一个函数可能会因为超宽看不到全部,具体请参照文章附件中的源代码。 附件下载:http://download.nocoo.us/Download/Archive/TreeViewCode.rar

TreeNode.cs

/// <summary>
/// TreeView结点类
/// </summary>
public class TreeNode
{
    private string name;
    private string href;
    private List<TreeNode> subNodes = new List<TreeNode>();

    /// <summary>
    /// 结点名
    /// </summary>
    public string Name { get { return name; } }
    /// <summary>
    /// 结点链接
    /// </summary>
    public string Href { get { return href; } }
    /// <summary>
    /// 下级结点个数
    /// </summary>
    public int Count { get { return this.subNodes.Count; } }
    /// <summary>
    /// 获取或者设置下级结点
    /// </summary>
    /// <param name="index">序号</param>
    /// <returns>下级结点</returns>
    public TreeNode this[int index]
    {
        get { return subNodes[index]; }
        set { subNodes[index] = value; }
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="name">结点名</param>
    public TreeNode(string name)
    {
        this.name = name;
        this.href = null;
    }

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="name">结点名</param>
    /// /// <param name="href">结点链接</param>
    public TreeNode(string name, string href)
    {
        this.name = name;
        this.href = href;
    }

    /// <summary>
    /// 添加下级结点
    /// </summary>
    /// <param name="node">新结点</param>
    public void Add(TreeNode node)
    {
        subNodes.Add(node);
    }
}

TreeView.cs

/// <summary>
/// TreeView
/// </summary>
public class TreeView
{
    private List<TreeNode> nodes = new List<TreeNode>();

    /// <summary>
    /// 填充测试用数据
    /// </summary>
    public void FillTestData()
    {
        TreeNode node1 = new TreeNode("中国", "#");
        TreeNode node11 = new TreeNode("华北地区", "#");
        TreeNode node111 = new TreeNode("河南省", "#");
        TreeNode node112 = new TreeNode("河北省", "#");
        TreeNode node113 = new TreeNode("山东省", "#");
        TreeNode node1131 = new TreeNode("青岛市", "#");
        TreeNode node1132 = new TreeNode("济南市", "#");
        TreeNode node11321 = new TreeNode("市中区", "#");
        TreeNode node11322 = new TreeNode("历下区", "#");
        TreeNode node11323 = new TreeNode("槐荫区", "#");
        TreeNode node11324 = new TreeNode("天桥区", "#");
        TreeNode node11325 = new TreeNode("长清区", "#");
        TreeNode node1133 = new TreeNode("菏泽市", "#");
        TreeNode node1134 = new TreeNode("济宁市", "#");
        TreeNode node1135 = new TreeNode("德州市", "#");
        TreeNode node12 = new TreeNode("东北地区", "#");
        TreeNode node13 = new TreeNode("西北地区", "#");
        TreeNode node14 = new TreeNode("华东地区", "#");
        TreeNode node15 = new TreeNode("西南地区", "#");
        TreeNode node16 = new TreeNode("华南地区", "#");
        TreeNode node17 = new TreeNode("华中地区", "#");
        TreeNode node18 = new TreeNode("港澳台地区", "#");

        node1132.Add(node11321);
        node1132.Add(node11322);
        node1132.Add(node11323);
        node1132.Add(node11324);
        node1132.Add(node11325);

        node113.Add(node1131);
        node113.Add(node1132);
        node113.Add(node1133);
        node113.Add(node1134);
        node113.Add(node1135);

        node11.Add(node111);
        node11.Add(node112);
        node11.Add(node113);

        node1.Add(node11);
        node1.Add(node12);
        node1.Add(node13);
        node1.Add(node14);
        node1.Add(node15);
        node1.Add(node16);
        node1.Add(node17);
        node1.Add(node18);

        nodes.Add(node1);
        nodes.Add(new TreeNode("俄罗斯", ""));
        nodes.Add(new TreeNode("美国"));
        nodes.Add(new TreeNode("韩国"));
        nodes.Add(new TreeNode("澳大利亚"));
        nodes.Add(new TreeNode("印度", ""));
        nodes.Add(new TreeNode("加拿大", ""));
    }

    /// <summary>
    /// 获取TreeView的html代码
    /// </summary>
    /// <returns></returns>
    public string GetHtmlString()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("<ul>");
        for (int i = 0; i < nodes.Count; i++)
        {
            sb.AppendLine(GetNodeHtml(nodes[i], 1, (i + 1).ToString()));
        }
        sb.AppendLine("</ul>");
        return sb.ToString();
    }

    private string GetNodeHtml(TreeNode thisNode, int depth, string id)
    {
        StringBuilder sb = new StringBuilder();
        bool hasSub = (thisNode.Count > 0) ? true : false;
        sb.AppendLine(string.Format("<li id=\"depth_{0}_item_{1}\">", depth, id));
        sb.AppendLine(string.Format(
            "<div class=\"{0}\" id=\"depth_{1}_item_{2}_ico\" onclick=\"controlNode(this,'depth_{1}_item_{2}')\"></div><h1>{3}</h1>",
            hasSub ? "closedir" : "nodir",
            depth,
            id,
            (thisNode.Href == null || thisNode.Href.Equals("")) ? thisNode.Name : string.Format("<a href=\"{0}\">{1}</a>", thisNode.Href, thisNode.Name)
            ));
        if (hasSub)
        {
            sb.AppendLine(string.Format("<div id=\"depth_{0}_item_{1}_layer\" style=\"display:block;\">", depth, id));
            sb.AppendLine("<ul>");
            for (int i = 0; i < thisNode.Count; i++)
            {
                sb.AppendLine(GetNodeHtml(thisNode[i], depth + 1, string.Format("{0}_{1}", id, i + 1)));
            }
            sb.AppendLine("</ul>");
            sb.AppendLine("</div>");
        }
        sb.AppendLine("</li>");
        return sb.ToString();
    }
}

ASP.NET页面调用:

<%
    CMC.TreeView list = new CMC.TreeView();
    list.FillTestData();
    Response.Write(list.GetHtmlString());
%>

ASP.NET页面JavaScript:

defaultNodeState();

function defaultNodeState()
{
	var nodeState = getCookie("nodeState");
	if(nodeState == null)
	{
	    nodeState = ",|,|,";
		setCookie("nodeState",nodeState);
	}
	var layer = nodeState.split('|');
	for(var i=0;i<layer.length;i++)
	{
		if(layer[i] != ",")
		{
			var lItem = layer[i].split(',');
			var nodeIco = document.getElementById(lItem[0]+"_ico");
			var nodeLayer = document.getElementById(lItem[0]+"_layer");
			OpenNode(nodeIco);
			ShowDiv(nodeLayer);
		}
	}
}
function controlNode(obj,layerId)
{
	var className = obj.className.toLowerCase();
	var layer = document.getElementById(layerId + "_layer");

	cookiesNode(layerId, className);
	if(className == "opendir")
	{
		HideDiv(layer);
		obj.className = "closedir";
	}
	else if (className == "closedir")
	{
		ShowDiv(layer);
		obj.className = "opendir";
	}
}

function cookiesNode(layerId,className)
{
    var nodeState = getCookie("nodeState");
	if(nodeState == null)
	{
	    nodeState = ",|,|,";
		setCookie("nodeState",nodeState);
	}
	var layer = nodeState.split('|');
	var lDepth = getDepth(layerId);
	if(className == "opendir")
	{

		layer[lDepth-1] = ","
	}
	else
	{
		if(layer[lDepth-1] &&amp layer[lDepth-1] != ",") {
                        var lItem = layer[lDepth - 1].split(',');
			var lIco = document.getElementById(lItem[0]+"_ico");
			var lLayer = document.getElementById(lItem[0] + "_layer");
			HideDiv(lLayer);
			CloseNode(lIco);
			    }
			    layer[lDepth - 1] = layerId + "," + lDepth;
		    }
	var cValue = layer[0];
	for(var i=1;i<layer.length;i++)
	{
		cValue += "|" + layer[i];
	}
	setCookie("nodeState",cValue);
}

function getDepth(layerId)
{
	var lItem = layerId.split('_');
	return lItem[1];
}

function OpenNode(obj)
{
	obj.className = "opendir";
}
function CloseNode(obj)
{
	obj.className = "closedir";
}
function HideDiv(obj)
{
    obj.style.display='none';

}
function ShowDiv(obj)
{
    obj.style.display='block';
}

//设置cookies
function setCookie(name,value)
{
    var Days = 30;
    var exp = new Date();
    exp.setTime(exp.getTime() + Days*24*60*60*1000);
    document.cookie = name + "=" + escape(value) +
      ";expires=" + exp.toGMTString();
}
//读取cookies
function getCookie(name)
{
    var arr,reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if(arr = document.cookie.match(reg)) return unescape(arr[2]);
    else return null;
}