ASTreeView - 免费的 ASP.NET TreeView 控件






4.91/5 (114投票s)
一个功能齐全的 ASP.NET TreeView 控件,包括拖放、Ajax 加载、上下文菜单、下拉式 TreeView。
Nuget 包
ASTreeView 现已发布到 Nuget.org。请使用以下命令进行安装(适用于 .Net Framework 4.0 及更高版本):
PM> Install-Package ASTreeView
或者,如果您面向 .Net Framework 2.0/3.5,请使用:
PM> Install-Package ASTreeView.Legacy
引言
ASTreeView
是一个功能齐全的 ASP.NET treeview
控件,支持拖放、Ajax 加载、上下文菜单、XML 导入/导出、复选框、选择、通过 Ajax 添加/编辑/删除节点。
背景
ASTreeView
基于 .NET Framework 2.0 开发。演示项目是 Visual Studio 2005 项目。ASTreeView
与 ASP.NET 2.0 及更高版本兼容。
ASTreeView
是免费的!这意味着您可以在任何地方使用它!
我将项目托管在 Google Code:请下载程序集和演示,查看演示,并在您的项目中将 ASTreeView
投入使用!
更新时间
我为 astreeview
注册了一个域名:http://www.astreeview.com。
Using the Code
以下是 ASTreeView
支持的功能
1. 拖放
用户可以在树内甚至树之间拖放节点!
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx。
<ct:ASTreeView ID="astvMyTree"
runat="server"
BasePath="~/Javascript/astreeview/"
DataTableRootNodeValue="0"
EnableRoot="false"
EnableNodeSelection="false"
EnableCheckbox="true"
EnableDragDrop="true"
EnableTreeLines="true"
EnableNodeIcon="true"
EnableCustomizedNodeIcon="true"
EnableContextMenu="true"
EnableDebugMode="false"
EnableContextMenuAdd="false" />
在后端代码中
protected void btnToggleDragDrop_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableDragDrop = !this.astvMyTree.EnableDragDrop;
}
protected void btnToggleTreeLines_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableTreeLines = !this.astvMyTree.EnableTreeLines;
}
protected void btnToggleNodeIcon_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableNodeIcon = !this.astvMyTree.EnableNodeIcon;
}
protected void btnToggleCheckbox_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableCheckbox = !this.astvMyTree.EnableCheckbox;
}
protected void btnToggleDefaultNodeIcon_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableCustomizedNodeIcon =
!this.astvMyTree.EnableCustomizedNodeIcon;
}
protected void btnToggleContextMenu_Click( object sender, EventArgs e )
{
this.astvMyTree.EnableContextMenu = !this.astvMyTree.EnableContextMenu;
}
2. 树线
可启用/禁用树线。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx。
3. 树节点图标
开发人员可以为每个节点指定自定义图标,使用默认节点图标,或禁用节点图标。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx。
4. 复选框
支持三态(选中、未选中、半选中)复选框。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx。
5. 树节点上下文菜单
用户可以通过右键单击节点使用上下文菜单来编辑/删除节点。支持 Ajax 编辑/删除。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo3.aspx。
6. 支持多数据源
开发人员可以绑定不同类型的数据源(目前 astreeview
支持 datatable
和 XML datasource
)。或者开发人员可以创建 ASTreeViewNode
并将其添加到代码中的树中。
XML
DataTable
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo4.aspx。
7. 支持服务器端事件
提供 OnSelectedNodeChanged
和 OnCheckedNodeChanged
。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo2.aspx。
配置
<ct:ASTreeView ID="astvMyTree"
runat="server"
BasePath="~/Javascript/astreeview/"
DataTableRootNodeValue="0"
EnableRoot="false"
EnableNodeSelection="true"
EnableCheckbox="true"
EnableDragDrop="false"
EnableTreeLines="true"
EnableNodeIcon="true"
EnableCustomizedNodeIcon="false"
AutoPostBack="true"
EnableDebugMode="false"
EnableContextMenu="false"
OnOnCheckedNodeChanged="astvMyTree_OnCheckedNodeChanged"
OnOnSelectedNodeChanged="astvMyTree_OnSelectedNodeChanged" />
在后端代码中
protected void astvMyTree_OnCheckedNodeChanged
( object src, ASTreeViewNodeCheckedEventArgs e )
{
string toConsole = string.Format( ">>OnCheckedNodeChanged checked:
text:{0} value:{1} state:{2}", e.NodeText, e.NodeValue,
e.CheckedState.ToString() );
this.divConsole.InnerHtml += ( toConsole + "<br />" );
}
protected void astvMyTree_OnSelectedNodeChanged( object src,
ASTreeViewNodeSelectedEventArgs e )
{
string toConsole = string.Format( ">>OnSelectedNodeChanged selected:
text:{0} value:{1}", e.NodeText, e.NodeValue );
this.divConsole.InnerHtml += ( toConsole + "<br />" );
}
protected void btnGetSelectedNode_Click( object sender, EventArgs e )
{
string toConsole = string.Empty;
ASTreeViewNode selectedNode = astvMyTree.GetSelectedNode();
if( selectedNode == null )
toConsole = ">>no node selected.";
else
toConsole = string.Format( ">>node selected: text:{0} value:{1}",
selectedNode.NodeText, selectedNode.NodeValue );
this.divConsole.InnerHtml += ( toConsole + "<br />" );
}
protected void btnGetCheckedNodes_Click( object sender, EventArgs e )
{
List<ASTreeViewNode> checkedNodes = this.astvMyTree.GetCheckedNodes
( cbIncludeHalfChecked.Checked );
StringBuilder sb = new StringBuilder();
foreach( ASTreeViewNode node in checkedNodes )
sb.Append( string.Format( "[text:{0}, value:{1}]<br />",
node.NodeText, node.NodeValue ) );
this.divConsole.InnerHtml += ( string.Format( ">>nodes checked:
<div style='padding-left:20px;'>{0}</div>", sb.ToString() ) );
}
8. 支持 Ajax 节点加载
有数千个节点?没问题,ASTreeView
支持使用 Ajax 加载节点。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo5.aspx。
配置
<ct:ASTreeView ID="astvMyTree"
runat="server"
BasePath="~/Javascript/astreeview/"
DataTableRootNodeValue="0"
EnableRoot="false"
EnableNodeSelection="true"
EnableCheckbox="true"
EnableDragDrop="false"
EnableTreeLines="true"
EnableNodeIcon="true"
EnableCustomizedNodeIcon="false"
EnableContextMenu="true"
EnableDebugMode="false"
EnableAjaxOnEditDelete="true"
AddNodeProvider="~/ASTreeViewDemo5.aspx"
AdditionalAddRequestParameters="{'t2':'ajaxAdd'}"
EditNodeProvider="~/ASTreeViewRenameNodeHandler.aspx"
DeleteNodeProvider="~/ASTreeViewDeleteNodeProvider.aspx"
LoadNodesProvider="~/ASTreeViewDemo5.aspx"
AdditionalLoadNodesRequestParameters="{'t1':'ajaxLoad'}"/>
在后端代码中
protected override void Render( HtmlTextWriter writer )
{
if( Request.QueryString["t1"] == "ajaxLoad" )
{
string virtualParentKey = Request.QueryString["virtualParentKey"];
string para = string.Empty;// "= 1";
if( virtualParentKey == null )
para = " is NULL";
else
para = "=" + virtualParentKey;
string sql = @"SELECT p1.[ProductID] as
ProductID, p1.[ProductName] as ProductName,
p1.[ParentID] as ParentID, p3.childNodesCount as ChildNodesCount
FROM [Products] p1
LEFT OUTER JOIN
(
SELECT COUNT(*) AS childNodesCount , p2.[ParentID] AS pId
FROM [Products] p2
GROUP BY p2.[ParentID]
) p3
ON p1.[ProductID] = p3.pId
WHERE p1.[ParentID] " + para;
DataTable dt = OleDbHelper.ExecuteDataset( base.NorthWindConnectionString,
CommandType.Text, sql ).Tables[0];
ASTreeViewNode root = new ASTreeViewNode( "root" );
foreach( DataRow dr in dt.Rows )
{
string productName = dr["ProductName"].ToString();
string productId = dr["ProductID"].ToString();
string parentId = dr["ParentID"].ToString();
int childNodesCount = 0;
if( !string.IsNullOrEmpty( dr["ChildNodesCount"].ToString() ) )
childNodesCount = int.Parse( dr["ChildNodesCount"].ToString() );
ASTreeViewLinkNode node = new ASTreeViewLinkNode( productName, productId );
node.VirtualNodesCount = childNodesCount;
node.VirtualParentKey = productId;
node.IsVirtualNode = childNodesCount > 0;
node.NavigateUrl = "#";
node.AddtionalAttributes.Add( new KeyValuePair<string, string>
( "onclick", "return false;" ) );
root.AppendChild( node );
}
HtmlGenericControl ulRoot = new HtmlGenericControl( "ul" );
astvMyTree.TreeViewHelper.ConvertTree( ulRoot, root, false );
foreach( Control c in ulRoot.Controls )
c.RenderControl( writer );
}
else if( Request.QueryString["t2"] == "ajaxAdd" )
{
string addNodeText = Request.QueryString["addNodeText"];
int parentNodeValue = int.Parse( Request.QueryString["parentNodeValue"] );
string maxSql = "select max( productId ) from products";
int max = (int)OleDbHelper.ExecuteScalar
( base.NorthWindConnectionString, CommandType.Text, maxSql );
int newId = max + 1;
string sql = string.Format( @"INSERT INTO products
( productid, Discontinued, productname, parentid ) values( {0} ,0, '{1}', {2})"
, max + 1, addNodeText.Replace( "'", "''" ), parentNodeValue );
int i = OleDbHelper.ExecuteNonQuery
( base.NorthWindConnectionString, CommandType.Text, sql );
ASTreeViewNode root = new ASTreeViewNode( "root" );
ASTreeViewLinkNode node = new ASTreeViewLinkNode
( addNodeText, newId.ToString() );
node.NavigateUrl = "#";
node.AddtionalAttributes.Add( new KeyValuePair<string,
string>( "onclick", "return false;" ) );
root.AppendChild( node );
HtmlGenericControl ulRoot = new HtmlGenericControl( "ul" );
astvMyTree.TreeViewHelper.ConvertTree( ulRoot, root, false );
foreach( Control c in ulRoot.Controls )
c.RenderControl( writer );
}
else
base.Render( writer );
}
9. 多类型树节点
树节点可以是超链接或 LinkButton
以执行回发。
查看实时演示
- 超链接:http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx
- 链接按钮:http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo2.aspx
10. ASDropDownTree
ASDropDownTree
继承自 ASTreeView
,外观类似于 DropDownList
,根据控件配置支持多选和单选。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo6.aspx。
11. 树之间的(甚至跨树)拖放
节点可以跨树拖放。
查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo7.aspx。
12. 扩展上下文菜单
现在可以将自定义的 ContextMenu
项添加到菜单中。截图
添加自定义菜单非常简单
/// <summary>
/// initial controls, bind you events etc. here
/// </summary>
private void InitializeComponent()
{
this.astvMyTree.ContextMenu.MenuItems.Add( new ASContextMenuItem(
"Custom Menu 1", "alert('current value:' + "
+ this.astvMyTree.ContextMenuClientID
+ ".getSelectedItem().parentNode.getAttribute('treeNodeValue')"
+ ");return false;", "otherevent" ) );
this.astvMyTree.ContextMenu.MenuItems.Add( new ASContextMenuItem(
"Custom Menu 2", "alert('current text:' + "
+ this.astvMyTree.ContextMenuClientID
+ ".getSelectedItem().innerHTML"
+ ");return false;", "otherevent" ) );
}
在线演示:http://www.astreeview.com/astreeviewdemo/ASTreeViewDemo3.aspx。
13. 扩展上下文菜单
在 1.3.0 版本中,最终用户可以通过单击节点文本来打开文件夹。这对于仅叶子节点可点击的情况很有用,例如书签。
要启用此功能,只需设置 ASTreeView
的“EnableParentNodeExpand
”属性。
14. 使用 HTML 自定义节点
NodeText
可以是 HTML。
this.astvMyTree.RootNode
.AppendChild( new ASTreeViewLinkNode
( "Accor <a href='http://www.astreeview.com' target='_blank'>see demo</a>"
, "Accor"
, "http://www.accor.com", "_self", "Goto Accor", "~/Images/demoIcons/accor.gif" )
.AppendChild( new ASTreeViewLinkNode( "Accor Services",
"Accor Services", http://www.accorservices.com,
"_self", "Goto Accor Services", "~/Images/demoIcons/accorservices.gif" ) )
.AppendChild( new ASTreeViewLinkNode( "Accor Hospitality",
"Accor Hospitality", "http://www.accorhotels.com", "_self",
"Goto Accor Hospitality", "~/Images/demoIcons/accorhospitality.gif" ) )
);
15. 主题
ASTreeView
现在支持主题!开发人员可以轻松地为 treeview
创建自己的主题。请查看 演示。
屏幕截图
16. 从右到左支持
ASTreeView
现在支持 RTL 显示,感谢 Mojtaba Vali 的建议!也请查看 演示。
17. 支持将 HTML 作为 TreeNodeText
在新版本中,您可以使用 HTML 作为树节点文本,而不仅仅是纯文本。
18. 支持多行编辑模式
将 EnableMultiLineEdit
属性设置为 true
以启用此功能,默认值为 false
。
19. 拖放完成事件现已可用。
我在拖放后添加了一个新的客户端事件。使用方法
<script type="text/javascript">
//parameter must be "elem"
function dndHandler( elem ){
document.getElementById( "<%=divConsole.ClientID %>" ).innerHTML
+= ( ">>node dragged:"
+ elem.getAttribute("treeNodeValue")
+ "<br />" );
}
</script>
然后设置 OnNodeDragAndDropCompleteScript="dndHandler( elem )"
,访问 演示。
屏幕截图
20. ASTreeViewNode 的新属性 – EnableChildren
将此属性设置为 false
可以禁止将其他节点拖放到当前节点作为子节点。请参考 示例 1 查看效果。
21. 垂直拖放节点
如果您将 ASTreeView
用作列表,可以将 EnableHorizontalLock
设置为 true
,这样最终用户只能上下移动节点,而不能左右移动。
屏幕截图
22. 修复拖放深度
如果您希望最终用户只能在与原始级别相同的级别内移动节点,可以将属性 EnableFixedDepthDragDrop=true
设置为 true
,这样节点只能拖放到与其原始级别相同的级别,访问 在线演示。
23. 添加 OnNodeDragAndDropStartScript 事件
现在为开发人员提供了一个新的事件 OnNodeDragAndDropStartScript
,以便在最终用户开始拖动节点时执行一些 JS。以下是一个使用示例
为 astreeview
添加一个属性
OnNodeDragAndDropStartScript="dndStartHandler( elem )"
处理开始拖放的 JS 函数
//parameter must be "elem"
functiondndStartHandler( elem ){
document.getElementById("").innerHTML
+= (">>drag started. [Node]"+ elem.getAttribute("treeNodeValue")
+" [Parent]:"+ elem.parentNode.parentNode.getAttribute("treeNodeValue")
+"
");
}
24. 新节点类型:TextNode
树节点的內容现在更加灵活。您可以在新的节点类型 – TextNode
中添加 HTML、JavaScript。
屏幕截图
25. 支持自定义 JavaScript 处理程序
例如,如果开发人员希望在服务器返回指定条件时取消添加节点操作。他可以
- 设置
EnableOnNodeAddedScriptReturn="true"
- 设置
OnNodeAddedScript="addedHandler(elem)"
- 编写
addedHandler
function addedHandler( elem ){ var message = ''; var result = true; var aTag = elem.getElementsByTagName('A')[0]; if( aTag.getAttribute('addfailed') == 'true' ){ alert( aTag.innerHTML ); return false; } else{ message = (">>add completed. [Node]" + elem.getAttribute("treeNodeValue") + "<br />" ); } document.getElementById("").innerHTML += message; return result; }
在这种情况下,当服务器端返回的节点中包含 addfailed
时,astreeview
将取消添加操作。
同样的方法也可以应用于编辑、删除和拖放。
一些截图
26. 新增 API (1.5.8)
1.5.8 版本新增 API
SelectNode
– 按节点值选择节点CheckNodes
– 按节点值选中节点UnCheckNodes
- 按节点值取消选中节点FindByValue
– 按节点值查找节点,类似于WebControl
中的FindControl
FindByText
– 按节点文本查找节点
27. ASDropDownTreeView 中的启用/禁用功能
开发人员现在可以设置 ASDropDownTreeView
的 Enabled
属性来启用/禁用它。
aspx 中的配置
this.astvMyTree.Enabled = false;
28. ASTreeViewNode 的 EnableOpenClose 属性
现在可以移除树节点前面的加号/减号图标。这适用于某些节点需要始终展开的情况。只需将 EnableOpenClose 设置为 false 即可移除展开/折叠图标。
someNode.EnableOpenClose = false;
29. [重要] 1.5.8 版本中的拖放 API 更改
在新版本中,我将 OnNodeDragAndDropCompleteScript
更改为 OnNodeDragAndDropCompletingScript,并添加了一个新的 API 称为 OnNodeDragAndDropCompletedScript。
新 API 之间的区别
在 OnNodeDragAndDropCompleting
中,您无法获取当前节点的同级新节点,因为拖放尚未完成。但此时您可以取消拖放。
在 OnNodeDragAndDropCompleted
中,您无法取消拖放,因为节点已附加到新节点。但此时,您可以获取当前节点的新父节点、新同级节点。
如果您要更新到 1.5.8 版本并且正在使用节点拖放事件,请更新您的代码,将 OnNodeDragAndDropComplete
更改为 OnNodeDragAndDropCompleting
以保持相同的行为。
支持
为了妥善管理请求,我设置了一个 mantis 系统用于提交请求和错误。请在 http://www.astreeview.com/astreeviewdemo/Support.aspx 查找 Mantis 链接。
关注点
我花了两个月到三个月的时间进行开发,ASTreeView 终于完成了。现在我想向大家介绍它。非常感谢您的反馈!
历史
ASTreeView
的当前版本是 1.5.8,查看详情。
在 1.5.8 版本中,添加了若干新功能
- 新增 API
- ASDropDownTreeView 中的启用/禁用功能
- ASTreeViewNode 的 EnableOpenClose 属性
- [重要] 拖放 API 更改
在 1.5.5 版本中,添加了若干新功能
- 为检查、选择和查找节点添加了新 API:
SelectNode
、CheckNodes
、UnCheckNodes
、FindByValue
、FindByText
- 添加了新的节点类型:
TextNode
- 添加了 EnableDragDropOnIcon 属性
- 支持自定义 JavaScript 处理程序
- 改进了 ASTreeView 的 CSS
- 改进了 ViewState 管理
- 强命名程序集
在 1.4.0 版本中,添加了若干新功能
- 垂直拖放节点
- 修复拖放深度
- 添加 OnNodeDragAndDropStartScript 事件
- 修复了若干 bug
在 1.3.0 版本中,添加了若干新功能
- 主题
- 从右到左支持
- 支持将 HTML 作为 TreeNodeText
- 支持转义编辑/添加输入
- 支持多行编辑模式
- 拖放完成事件现已可用
- ASTreeViewNode 的新属性 – EnableChildren