如下图所示:
该控件为无限级扩展的,只需要指定其子节点字段名(默认为ID),父节点字段名(默认为parentID),以及第一层父节点的值即可(默认为0)。
1.首先定义常量
protected
const
string
strT
=
"
├
"
;
protected const string strL = " └ " ;
protected const string strI = " │ " ;
protected DataTable tempTable;
protected int lay = 0 ; // 节点层数
protected int level = 0 ; // DropDownList顺序
protected const string strL = " └ " ;
protected const string strI = " │ " ;
protected DataTable tempTable;
protected int lay = 0 ; // 节点层数
protected int level = 0 ; // DropDownList顺序
2.添加属性
[Category( " 数据 " ),Description( " 第一层父节点的值 " )]
public int FirstParentValue
{
get
{
object obj = ViewState[ " FirstParentValue " ];
return ((obj == null ) ? 0 :( int )obj);
}
set
{
ViewState[ " FirstParentValue " ] = value;
}
}
[Category( " 数据 " ),Description( " 子字段名 " )]
public string ChildField
{
get
{
object obj = ViewState[ " ChildField " ];
return ((obj == null ) ? " ID " :( string )obj);
}
set
{
ViewState[ " ChildField " ] = value;
}
}
[Category( " 数据 " ),Description( " 父字段名 " )]
public string ParentField
{
get
{
object obj = ViewState[ " ParentField " ];
return ((obj == null ) ? " parentID " :( string )obj);
}
set
{
ViewState[ " ParentField " ] = value;
}
}
[Category( " 数据 " ),Description( " 显示文本字段名 " )]
public string ShowText
{
get
{
object obj = ViewState[ " ShowText " ];
return ((obj == null ) ? " name " :( string )obj);
}
set
{
ViewState[ " ShowText " ] = value;
}
}
3.计算当前节点所在的层以及是否为子节点,是否有兄弟节点等函数,用于生成树形
/// <summary>
/// 递归算出指定ID所在树中的层数
/// </summary>
/// <param name="treeTable"></param>
/// <param name="ID"> 节点ID </param>
private void FindLay(DataTable treeTable, int ID)
{
for ( int i = 0 ;i < treeTable.Rows.Count;i ++ )
{
if (ID == int .Parse(treeTable.Rows[i][ this .ChildField].ToString()))
{
int parentID = int .Parse(treeTable.Rows[i][ this .ParentField].ToString());
// 如果父节点不是根节点,递归
if (parentID != 0 )
{
lay ++ ;
FindLay(treeTable, int .Parse(treeTable.Rows[i][ this .ParentField].ToString()));
}
}
}
}
/// <summary>
/// 判断是否有子接点
/// </summary>
/// <param name="dt"></param>
/// <param name="ID"> 当前节点的ID </param>
/// <returns></returns>
private bool IsExistChildNodes(DataTable dt, string ID)
{
bool flag = false ;
if (ID == null )
return flag;
for ( int i = 0 ;i < dt.Rows.Count;i ++ )
{
if (dt.Rows[i][ this .ParentField].ToString() == ID)
{
flag = true ;
return flag;
}
else
{
flag = false ;
}
}
return flag;
}
/// <summary>
/// 判断是否有兄弟节点
/// </summary>
/// <param name="dt"></param>
/// <param name="ID"> 当前节点的ID </param>
/// <returns></returns>
private bool IsBorthorNodes(DataTable dt, string ID)
{
bool flag = false ;
if (ID == null )
return flag;
for ( int i = 0 ;i < dt.Rows.Count;i ++ )
{
if (dt.Rows[i][ this .ChildField].ToString() == ID && i < dt.Rows.Count - 1 )
{
if (dt.Rows[i][ this .ParentField].ToString() == dt.Rows[i + 1 ][ this .ParentField].ToString())
{
flag = true ;
return flag;
}
else
{
flag = false ;
return flag;
}
}
}
return flag;
}
/// <summary>
/// 判断当前节点是否为子节点
/// </summary>
/// <param name="dt"></param>
/// <param name="ID"></param>
/// <returns></returns>
private bool IsChildNode(DataTable dt, string ID)
{
bool flag = false ;
if (ID == null )
return flag;
for ( int i = 0 ;i < dt.Rows.Count;i ++ )
{
if (dt.Rows[i][ this .ChildField].ToString() == ID)
{
if (dt.Rows[i][ this .ParentField].ToString() == " 0 " )
{
flag = false ;
return flag;
}
else
{
flag = true ;
return flag;
}
}
}
return flag;
}
4.递归生成树形
/// <summary>
/// 数据添加并生成树形
/// </summary>
/// <param name="dt"></param>
/// <param name="ID"></param>
private void BindData(DataTable dt, string ID)
{
DataRow[] dr;
dr = dt.Select( this .ParentField + " = " + ID, this .ChildField + " ASC " );
for ( int x = 0 ;x < dr.Length;x ++ )
{
string str = "" ;
lay = 0 ;
this .FindLay(dt, int .Parse(dr[x][ this .ChildField].ToString()));
if ( this .IsChildNode(dt,dr[x][this.ChildField ].ToString()) == true )
{
for ( int i = 0 ;i < lay;i ++ )
{
str += strI;
}
if ( this .IsBorthorNodes(dt,dr[x][ " id " ].ToString()) == true )
{
this .Items.Insert(level, new ListItem(str + strT + dr[x][this.ShowText ].ToString(),dr[x][this.ChildField ].ToString()));
}
else
{
this .Items.Insert(level, new ListItem(str + strL + dr[x][this.ShowText ].ToString(),dr[x][this.ChildField ].ToString()));
}
}
else
{
this .Items.Insert(level, new ListItem(str + dr[x][this.ShowText ].ToString(),dr[x][this.ChildField ].ToString()));
}
level += 1 ;
this .BindData(dt,dr[x][ this .ChildField].ToString()); // 递归生成树
}
}
5.绑定数据
/// <summary>
/// 绑定数据
/// </summary>
/// <param name="dt"> 数据源DataTable </param>
public void BindListData(DataTable dt)
{
tempTable = dt.Clone();
this .BindData(dt, this .FirstParentValue.ToString());
}
使用的时候调用该函数进行数据绑定!
在ASP.NET中实现这个真费劲,在Silverlight中实现就方便多了。