一个树控件类的实现---打造自己的树控件
原因:
当前的树控件或多或少存在各种各样的问题,有样式的,有速度的,与IE7兼容性问题的。而且因为没有源码,处理这些问题时非常麻烦。通常,在使用树控件时只需使用很简单的一些功能,收缩/展开,链接等。即然如此,为什么不可以自己实现一个满足这些简单功能的树呢?自已的东西,就算再烂,出现问题时,也知道怎么处理呀。
设计思路:
树控件最后解析成HTML代码的时候是什么呢?有的控件是DIV,有的是Table,本人认为用table更好控制。所以我的方案采取直接绘表格的方式实现,至于添加子节点,其实也就是表格中套表格了。
1、直接画Table,每个节点就是表格的一行。
2、每行分为两列,图标为一列,显示文本为一列。
3、第一级节点与子节点分开实现。
4、实现节点可以添加子节点方法。
5、提供点击事件处理接口,具体的点击方法在使用时由用户自己实现。
效果演示:
类代码:
代码说明:
图标文件:0.gif;e.gif;c.gif放在images文件夹中,在需要用该树的时候加到工程中。这三个图标文件山前是从MSDN帮助中的树控件上下载下来的。
图标的点击事件方法是:imgclick(this),这个方法名已经写死了。山前比较懒不想做得太灵活。够用原则。
该方法就是点击图标实现展开/收缩效果。
方法具体如下:
function imgclick(obj)
{
var ii=obj.parentElement.id;
var di;
di = window.document.getElementById("tb"+ii).style.display;
if(di=="")
{
window.document.getElementById("tb"+ii).style.display = "none";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/c.gif";
}
}
else if(di=="none")
{
window.document.getElementById("tb"+ii).style.display = "";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/o.gif";
}
}
}
这个类怎么用呢?我们的设计思想是以直接绘表格的方式绘制树的。绘好之后肯定就是一段HTML代码。如果要请树在界面上显示出来。只需将树的Nodestring输出到界面即可。
给个示例
示例:
您可以在Page_load中输出Nodestring。也可以重载Rendercontrol方法
其中nodeclick(this)的代码你可以写在aspx文件夹中。代码如下:
var selectobj;
function nodeclick(obj)
{
var ii=obj.parentElement.id;
var di;
di = window.document.getElementById("tb"+ii).style.display;
if(di=="")
{
window.document.getElementById("tb"+ii).style.display = "none";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/c.gif";
}
}
else if(di=="none")
{
window.document.getElementById("tb"+ii).style.display = "";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/o.gif";
}
}
if(selectobj!=null)
{
selectobj.style.backgroundColor = "#FFFFFF";
}
obj.style.backgroundColor = "#666666";
selectobj = obj;
}
总结:
该类提供了节点的点击事件,而且点击事件的具体方法用户可以随意定制。适用性较强。
而且采用直接绘表格的方式实现,进行样式处理会非常容易,也不会出现与浏览器兼容的问题。
当前的树控件或多或少存在各种各样的问题,有样式的,有速度的,与IE7兼容性问题的。而且因为没有源码,处理这些问题时非常麻烦。通常,在使用树控件时只需使用很简单的一些功能,收缩/展开,链接等。即然如此,为什么不可以自己实现一个满足这些简单功能的树呢?自已的东西,就算再烂,出现问题时,也知道怎么处理呀。
设计思路:
树控件最后解析成HTML代码的时候是什么呢?有的控件是DIV,有的是Table,本人认为用table更好控制。所以我的方案采取直接绘表格的方式实现,至于添加子节点,其实也就是表格中套表格了。
1、直接画Table,每个节点就是表格的一行。
2、每行分为两列,图标为一列,显示文本为一列。
3、第一级节点与子节点分开实现。
4、实现节点可以添加子节点方法。
5、提供点击事件处理接口,具体的点击方法在使用时由用户自己实现。
效果演示:
类代码:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Text.RegularExpressions;
namespace Shanqian.Component
{
public abstract class treenode
{
protected StringBuilder nodestring;
/// <summary>
/// 节点的HTML代码
/// </summary>
public StringBuilder Nodestring
{
get { return nodestring; }
set { nodestring = value; }
}
protected string script;
/// <summary>
/// 点击节点将触发的事件:JavaScript函数名称
/// </summary>
public string Script
{
get { return script; }
set { script = value; }
}
protected string text;
/// <summary>
/// 节点显示文本
/// </summary>
public string Text
{
get { return text; }
set { text = value; }
}
protected string value;
/// <summary>
/// 节点值
/// </summary>
public string Value
{
get { return value; }
set { this.value = value; }
}
protected string imgURL;
/// <summary>
/// 展开/收缩图标(一般不需要你去用)
/// </summary>
public string ImgURL
{
get { return imgURL; }
set { this.imgURL = value; }
}
protected string nodeStyle;
/// <summary>
/// 样式名称
/// </summary>
public string NodeStyle
{
get { return nodeStyle; }
set { this.nodeStyle = value; }
}
protected bool isExpand;
/// <summary>
/// 是否展开该节点
/// </summary>
public bool IsExpand
{
get { return isExpand; }
set { this.isExpand = value; }
}
/// <summary>
/// 在该节点下添加子节点
/// </summary>
/// <param name="node"></param>
public abstract void addChildNode(treenode node);
/// <summary>
/// 重置节点到初始状态。
/// </summary>
public abstract void init();
}
public class firstNode : treenode
{
public firstNode()
{
this.ImgURL = "images/c.gif";
}
public override void addChildNode(treenode node)
{
if (this.Nodestring == null)
{
this.ImgURL = "images/c.gif";
init();
}
if (node.Nodestring == null)
{
node.init();
}
if (node.IsExpand)
{
this.IsExpand = true;
Regex re = new Regex("style=\"display:none;\"");
string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);
Regex reImg = new Regex(this.ImgURL);
str = reImg.Replace(str, "images/o.gif", 1);
this.Nodestring.Remove(0, this.Nodestring.Length);
this.Nodestring.Append(str);
}
this.Nodestring.Insert(this.Nodestring.Length - 8, node.Nodestring.ToString());
}
public override void init()
{
string strid = System.Guid.NewGuid().ToString().Replace("-", "");
string strstyle = "";
if (!this.IsExpand)
{
strstyle = "display:none;";
}
else
{
this.ImgURL = "images/o.gif";
}
StringBuilder sb = new StringBuilder(100);
sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" onclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\""+this.NodeStyle+"\" onclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");
sb.Append("</table>");
this.Nodestring = sb;
}
}
public class childNode : treenode
{
public childNode()
{
this.ImgURL = "images/e.gif";
}
public override void addChildNode(treenode node)
{
if (this.Nodestring == null)
{
this.ImgURL = "images/c.gif";
init();
}
if (node.Nodestring == null)
{
node.init();
}
if (node.IsExpand)
{
this.IsExpand = true;
Regex re = new Regex("style=\"display:none;\"");
string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);
Regex reImg = new Regex(this.ImgURL);
str = reImg.Replace(str, "images/o.gif", 1);
this.Nodestring.Remove(0, this.Nodestring.Length);
this.Nodestring.Append(str);
}
this.Nodestring.Insert(this.Nodestring.Length - 18, node.Nodestring.ToString());
}
public override void init()
{
string strid = System.Guid.NewGuid().ToString().Replace("-", "");
string strstyle = "";
if (!this.IsExpand)
{
strstyle = "display:none;";
}
else
{
this.ImgURL = "images/o.gif";
}
StringBuilder sb = new StringBuilder(100);
sb.Append("<tr><td style=\"width:10px\"> </td><td>");
sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" onclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\"" + this.NodeStyle + "\" onclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");
sb.Append("</table></td></tr>");
this.Nodestring = sb;
}
}
}
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Text.RegularExpressions;
namespace Shanqian.Component
{
public abstract class treenode
{
protected StringBuilder nodestring;
/// <summary>
/// 节点的HTML代码
/// </summary>
public StringBuilder Nodestring
{
get { return nodestring; }
set { nodestring = value; }
}
protected string script;
/// <summary>
/// 点击节点将触发的事件:JavaScript函数名称
/// </summary>
public string Script
{
get { return script; }
set { script = value; }
}
protected string text;
/// <summary>
/// 节点显示文本
/// </summary>
public string Text
{
get { return text; }
set { text = value; }
}
protected string value;
/// <summary>
/// 节点值
/// </summary>
public string Value
{
get { return value; }
set { this.value = value; }
}
protected string imgURL;
/// <summary>
/// 展开/收缩图标(一般不需要你去用)
/// </summary>
public string ImgURL
{
get { return imgURL; }
set { this.imgURL = value; }
}
protected string nodeStyle;
/// <summary>
/// 样式名称
/// </summary>
public string NodeStyle
{
get { return nodeStyle; }
set { this.nodeStyle = value; }
}
protected bool isExpand;
/// <summary>
/// 是否展开该节点
/// </summary>
public bool IsExpand
{
get { return isExpand; }
set { this.isExpand = value; }
}
/// <summary>
/// 在该节点下添加子节点
/// </summary>
/// <param name="node"></param>
public abstract void addChildNode(treenode node);
/// <summary>
/// 重置节点到初始状态。
/// </summary>
public abstract void init();
}
public class firstNode : treenode
{
public firstNode()
{
this.ImgURL = "images/c.gif";
}
public override void addChildNode(treenode node)
{
if (this.Nodestring == null)
{
this.ImgURL = "images/c.gif";
init();
}
if (node.Nodestring == null)
{
node.init();
}
if (node.IsExpand)
{
this.IsExpand = true;
Regex re = new Regex("style=\"display:none;\"");
string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);
Regex reImg = new Regex(this.ImgURL);
str = reImg.Replace(str, "images/o.gif", 1);
this.Nodestring.Remove(0, this.Nodestring.Length);
this.Nodestring.Append(str);
}
this.Nodestring.Insert(this.Nodestring.Length - 8, node.Nodestring.ToString());
}
public override void init()
{
string strid = System.Guid.NewGuid().ToString().Replace("-", "");
string strstyle = "";
if (!this.IsExpand)
{
strstyle = "display:none;";
}
else
{
this.ImgURL = "images/o.gif";
}
StringBuilder sb = new StringBuilder(100);
sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" onclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\""+this.NodeStyle+"\" onclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");
sb.Append("</table>");
this.Nodestring = sb;
}
}
public class childNode : treenode
{
public childNode()
{
this.ImgURL = "images/e.gif";
}
public override void addChildNode(treenode node)
{
if (this.Nodestring == null)
{
this.ImgURL = "images/c.gif";
init();
}
if (node.Nodestring == null)
{
node.init();
}
if (node.IsExpand)
{
this.IsExpand = true;
Regex re = new Regex("style=\"display:none;\"");
string str = re.Replace(this.Nodestring.ToString(), "style=\"\"", 1);
Regex reImg = new Regex(this.ImgURL);
str = reImg.Replace(str, "images/o.gif", 1);
this.Nodestring.Remove(0, this.Nodestring.Length);
this.Nodestring.Append(str);
}
this.Nodestring.Insert(this.Nodestring.Length - 18, node.Nodestring.ToString());
}
public override void init()
{
string strid = System.Guid.NewGuid().ToString().Replace("-", "");
string strstyle = "";
if (!this.IsExpand)
{
strstyle = "display:none;";
}
else
{
this.ImgURL = "images/o.gif";
}
StringBuilder sb = new StringBuilder(100);
sb.Append("<tr><td style=\"width:10px\"> </td><td>");
sb.Append("<table border=\"0\"><tr id=\"" + strid + "\"><td style=\"width:5px\" onclick=\"imgclick(this);\"><img id=\"img" + strid + "\" src='" + this.ImgURL + "' /></td><td class=\"" + this.NodeStyle + "\" onclick=\"" + this.Script + "\">" + this.Text + "</td></tr></table>");
sb.Append("<table border=\"0\" cellpadding=\"0\" cellspacing =\"0\" id=\"tb" + strid + "\" style=\"" + strstyle + "\">");
sb.Append("</table></td></tr>");
this.Nodestring = sb;
}
}
}
代码说明:
图标文件:0.gif;e.gif;c.gif放在images文件夹中,在需要用该树的时候加到工程中。这三个图标文件山前是从MSDN帮助中的树控件上下载下来的。
图标的点击事件方法是:imgclick(this),这个方法名已经写死了。山前比较懒不想做得太灵活。够用原则。
该方法就是点击图标实现展开/收缩效果。
方法具体如下:
function imgclick(obj)
{
var ii=obj.parentElement.id;
var di;
di = window.document.getElementById("tb"+ii).style.display;
if(di=="")
{
window.document.getElementById("tb"+ii).style.display = "none";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/c.gif";
}
}
else if(di=="none")
{
window.document.getElementById("tb"+ii).style.display = "";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/o.gif";
}
}
}
这个类怎么用呢?我们的设计思想是以直接绘表格的方式绘制树的。绘好之后肯定就是一段HTML代码。如果要请树在界面上显示出来。只需将树的Nodestring输出到界面即可。
给个示例
示例:
您可以在Page_load中输出Nodestring。也可以重载Rendercontrol方法
protected void Page_Load(object sender, EventArgs e)
{
treenode tnf = new firstNode();
tnf.Text = "一级节点一";
tnf.IsExpand = true;
tnf.Script = "nodeclick(this);";
treenode tnc = new childNode();
tnc.Text = "二级节点一";
tnc.Script = "nodeclick(this);";
treenode tnc2 = new childNode();
tnc2.Text = "二级节点二";
tnc2.Script = "nodeclick(this);";
treenode tnc3 = new childNode();
tnc3.Text = "三级节点一";
tnc3.Script = "nodeclick(this);";
tnc.addChildNode(tnc3);
tnf.addChildNode(tnc);
tnf.addChildNode(tnc2);
this.Response.Write(tnf.Nodestring.ToString());
}
{
treenode tnf = new firstNode();
tnf.Text = "一级节点一";
tnf.IsExpand = true;
tnf.Script = "nodeclick(this);";
treenode tnc = new childNode();
tnc.Text = "二级节点一";
tnc.Script = "nodeclick(this);";
treenode tnc2 = new childNode();
tnc2.Text = "二级节点二";
tnc2.Script = "nodeclick(this);";
treenode tnc3 = new childNode();
tnc3.Text = "三级节点一";
tnc3.Script = "nodeclick(this);";
tnc.addChildNode(tnc3);
tnf.addChildNode(tnc);
tnf.addChildNode(tnc2);
this.Response.Write(tnf.Nodestring.ToString());
}
其中nodeclick(this)的代码你可以写在aspx文件夹中。代码如下:
var selectobj;
function nodeclick(obj)
{
var ii=obj.parentElement.id;
var di;
di = window.document.getElementById("tb"+ii).style.display;
if(di=="")
{
window.document.getElementById("tb"+ii).style.display = "none";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/c.gif";
}
}
else if(di=="none")
{
window.document.getElementById("tb"+ii).style.display = "";
var img =window.document.getElementById("img"+ii).src;
if(img.indexOf("images/e.gif")<0)
{
window.document.getElementById("img"+ii).src = "images/o.gif";
}
}
if(selectobj!=null)
{
selectobj.style.backgroundColor = "#FFFFFF";
}
obj.style.backgroundColor = "#666666";
selectobj = obj;
}
总结:
该类提供了节点的点击事件,而且点击事件的具体方法用户可以随意定制。适用性较强。
而且采用直接绘表格的方式实现,进行样式处理会非常容易,也不会出现与浏览器兼容的问题。