一个树控件,利用多线程实现.填充时采用非递归方式实现(TreeView的多叉链表结构似乎非常适合非递归方式).由于控件是同步加载的,树很大时可能速度比较慢,尽管采用了多线程.如果采用异步方式加载效果应该会更好.这个我还没写好,写好了再贴出来吧.代码如下:
/// <summary>
/// 树控件类
/// </summary>
public class TreeControl
{
protected TreeView treeView;
protected Page page;
protected HtmlGenericControl divTreeView;
protected HtmlGenericControl divTreeViewPanel;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="page">当前页面</param>
/// <param name="ctrlName">对控件的命名</param>
public TreeControl(Page page, string ctrlName)
{
this.page = page;
treeView = (TreeView)page.FindControl("tv" + ctrlName + "View");
if (treeView == null)
{
treeView = CreateCtl(ctrlName);
}
divTreeView = (HtmlGenericControl)page.FindControl("div" + ctrlName);
divTreeViewPanel = (HtmlGenericControl)page.FindControl("div" + ctrlName + "Panel");
treeView.Attributes.Add("onclick", "TreeViewGetData()");
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="page">当前页面</param>
/// <param name="ctrlName">对控件的命名</param>
/// <param name="currid">节点编号字段的名称</param>
/// <param name="menuName">显示信息字段的名称</param>
/// <param name="parentNode">父节点编号字段的名称</param>
/// <param name="tableName">表名称</param>
/// <param name="condition">条件</param>
/// <param name="order">排序</param>
public TreeControl(Page page, string ctrlName, string currid, string menuName, string parentNode, string tableName, string condition, string order)
{
this.page = page;
treeView = (TreeView)page.FindControl("tv" + ctrlName + "View");
if (treeView == null)
{
treeView = CreateCtl(ctrlName);
}
divTreeView = (HtmlGenericControl)page.FindControl("div" + ctrlName);
divTreeViewPanel = (HtmlGenericControl)page.FindControl("div" + ctrlName + "Panel");
treeView.Attributes.Add("onclick", "TreeViewGetData()");
LoadTree(currid, menuName, parentNode, tableName, condition, order);
Height = "150px";
}
/// <summary>
/// 装载树
/// </summary>
/// <param name="currid">节点编号字段的名称</param>
/// <param name="menuName">显示信息字段的名称</param>
/// <param name="parentNode">父节点编号字段的名称</param>
/// <param name="tableName">表名称</param>
/// <param name="condition">条件</param>
/// <param name="order">排序</param>
public void LoadTree(string currid, string menuName, string parentNode, string tableName, string condition, string order)
{
SQLServerDAL SSDal = new SQLServerDAL();
DataSet ds = new DataSet();
string sql = "select " + currid + " as currid, " + menuName + " as menuName, " + parentNode + " as parentNode from " + tableName;
if (condition != null && condition.Trim() != "")
{
sql += " where " + condition;
}
if (order != null && order.Trim() != "")
{
sql += " order by " + order;
}
ds = SSDal.returnRecordSet(sql);
//FillNode(null, ds);
FillParentNode(ds);
}
/// <summary>
/// 获取当前树控件
/// </summary>
public TreeView TreeViewCtl
{
get
{
return treeView;
}
}
/// <summary>
/// 获取当前树控件所在页面
/// </summary>
public Page PageCtl
{
get
{
return page;
}
}
/// <summary>
/// 控件宽度
/// </summary>
public string Width
{
get
{
return divTreeView.Style[HtmlTextWriterStyle.Width];
}
set
{
divTreeView.Style.Add(HtmlTextWriterStyle.Width, value);
}
}
/// <summary>
/// 控件高度
/// </summary>
public string Height
{
get
{
return divTreeView.Style[HtmlTextWriterStyle.Height];
}
set
{
divTreeView.Style.Add(HtmlTextWriterStyle.Height, value);
}
}
protected TreeView CreateCtl(string ctlName)
{
HtmlGenericControl divSelectTreeObj = new HtmlGenericControl("div");
divSelectTreeObj.ID = "div" + ctlName;
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Left, "100px");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Width, "150px");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Top, "100px");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.BackgroundColor, "#fffff2");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Display, "none");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Height, "150px");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.ZIndex, "999");
divSelectTreeObj.Style.Add(HtmlTextWriterStyle.Position, "absolute");
HtmlGenericControl divSelectTreePanelObj = new HtmlGenericControl("div");
divSelectTreePanelObj.ID = "div" + ctlName + "Panel";
divSelectTreePanelObj.Style.Add(HtmlTextWriterStyle.Width, "100%");
divSelectTreePanelObj.Style.Add(HtmlTextWriterStyle.Height, "100%");
divSelectTreePanelObj.Style.Add(HtmlTextWriterStyle.Overflow, "auto");
TreeView tvSelectTreeViewObj = new TreeView();
tvSelectTreeViewObj.ID = "tv" + ctlName + "View";
tvSelectTreeViewObj.ShowCheckBoxes = TreeNodeTypes.None;
tvSelectTreeViewObj.EnableViewState = false;
divSelectTreePanelObj.Controls.Add(tvSelectTreeViewObj);
divSelectTreeObj.Controls.Add(divSelectTreePanelObj);
page.Form.Controls.Add(divSelectTreeObj);
page.ClientScript.RegisterStartupScript(typeof(string), "init" + ctlName + "Style"
, "<script>document.all.div" + ctlName + ".className = 'layer';"
+ "document.all.div" + ctlName + "Panel.className = 'scroll';"
+ "document.all.div" + ctlName + "Panel.title = '按上下键或滚动鼠标滑轮可控制滑块!';"
+ "</script>");
return tvSelectTreeViewObj;
}
protected void FillNode(TreeNode pNode, DataSet ds)
{
DataView dvTree = new DataView(ds.Tables[0]);
dvTree.RowFilter = "[parentNode] = "
+ (pNode != null ? pNode.Value.Trim() + " and [parentNode] <> [currid]" : " - 1 or [parentNode] = [currid]");
foreach (DataRowView Row in dvTree)
{
TreeNode Node = new TreeNode();
Node.Text = Row["menuName"].ToString().Trim();
Node.Value = Row["currid"].ToString().Trim();
Node.SelectAction = TreeNodeSelectAction.None;
Node.ToolTip = "单击选中";
if (pNode == null)
{
treeView.Nodes.Add(Node);
}
else
{
pNode.ChildNodes.Add(Node);
pNode.Expanded = false;
}
FillNode(Node, ds);
}
}
protected class FillMsg
{
public TreeNode pNode;
public DataSet ds;
public FillMsg(TreeNode pNode, DataSet ds)
{
this.pNode = pNode;
this.ds = ds;
}
}
protected void ThreadFunc(object e)
{
FillMsg msg = (FillMsg)e;
FillChildNode(msg.pNode, msg.ds);
}
protected void FillParentNode(DataSet ds)
{
DataView dvTree = new DataView(ds.Tables[0]);
dvTree.RowFilter = "[parentNode] = - 1 or [parentNode] = [currid]";
Thread[] threadList = new Thread[dvTree.Count];
for (int i = 0; i < dvTree.Count; i++)
{
TreeNode Node = new TreeNode();
DataRowView Row = dvTree;
Node.Text = Row["menuName"].ToString().Trim();
Node.Value = Row["currid"].ToString().Trim();
Node.SelectAction = TreeNodeSelectAction.None;
Node.ToolTip = "单击选中";
treeView.Nodes.Add(Node);
threadList = new Thread(new ParameterizedThreadStart(ThreadFunc));
threadList.Start(new FillMsg(Node, ds));
}
while (true)
{
bool finish = true;
foreach (Thread thread in threadList)
{
if (thread.ThreadState != ThreadState.Stopped)
{
finish = false;
break;
}
}
if (finish)
{
break;
}
}
}
protected void FillChildNode(TreeNode pNode, DataSet ds)
{
DataView dvTree = new DataView(ds.Tables[0]);
while (pNode != null)
{
dvTree.RowFilter = "[parentNode] = " + pNode.Value.Trim() + " and [parentNode] <> [currid]";
if (dvTree.Count == 0)
{
while (pNode.Parent != null && pNode.Parent.ChildNodes.IndexOf(pNode) == pNode.Parent.ChildNodes.Count - 1)
{
pNode = pNode.Parent;
}
if (pNode.Parent == null)
{
break;
}
pNode = pNode.Parent.ChildNodes[pNode.Parent.ChildNodes.IndexOf(pNode) + 1];
continue;
}
foreach (DataRowView Row in dvTree)
{
TreeNode Node = new TreeNode();
Node.Text = Row["menuName"].ToString().Trim();
Node.Value = Row["currid"].ToString().Trim();
Node.SelectAction = TreeNodeSelectAction.None;
Node.ToolTip = "单击选中";
pNode.ChildNodes.Add(Node);
pNode.Expanded = false;
}
pNode = pNode.ChildNodes[0];
}
}
}
多线程非递归实现的树控件
最新推荐文章于 2019-11-21 09:28:42 发布