65.9K
CodeProject 正在变化。 阅读更多。
Home

ASTreeView - 免费的 ASP.NET TreeView 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (114投票s)

2009 年 10 月 14 日

CPOL

7分钟阅读

viewsIcon

2463099

downloadIcon

21241

一个功能齐全的 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. 拖放

用户可以在树内甚至树之间拖放节点!

astreeview_intro_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;
}

ASTreeView 演示

2. 树线

可启用/禁用树线。

astreeview_intro_2

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx

3. 树节点图标

开发人员可以为每个节点指定自定义图标,使用默认节点图标,或禁用节点图标。

astreeview_intro_3

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx

4. 复选框

支持三态(选中、未选中、半选中)复选框。

astreeview_intro_4

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo1.aspx

5. 树节点上下文菜单

用户可以通过右键单击节点使用上下文菜单来编辑/删除节点。支持 Ajax 编辑/删除。

astreeview_intro_5

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo3.aspx

6. 支持多数据源

开发人员可以绑定不同类型的数据源(目前 astreeview 支持 datatable 和 XML datasource)。或者开发人员可以创建 ASTreeViewNode 并将其添加到代码中的树中。

XML

astreeview_intro_6

DataTable

astreeview_intro_6-2

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo4.aspx

7. 支持服务器端事件

提供 OnSelectedNodeChangedOnCheckedNodeChanged

查看实时演示: 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 加载节点。

astreeview_intro_8

查看实时演示: 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 以执行回发。

astreeview_intro_9

查看实时演示

10. ASDropDownTree

ASDropDownTree 继承自 ASTreeView,外观类似于 DropDownList,根据控件配置支持多选和单选。

astreeview_intro_10

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo6.aspx

11. 树之间的(甚至跨树)拖放

节点可以跨树拖放。

astreeview_intro_11

查看实时演示: http://www.astreeview.com/ASTreeViewDemo/ASTreeViewDemo7.aspx

12. 扩展上下文菜单

现在可以将自定义的 ContextMenu 项添加到菜单中。截图

image

添加自定义菜单非常简单

/// <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 版本中,最终用户可以通过单击节点文本来打开文件夹。这对于仅叶子节点可点击的情况很有用,例如书签。

image

要启用此功能,只需设置 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 创建自己的主题。请查看 演示。

屏幕截图

image

16. 从右到左支持

ASTreeView 现在支持 RTL 显示,感谢 Mojtaba Vali 的建议!也请查看 演示

image

17. 支持将 HTML 作为 TreeNodeText

在新版本中,您可以使用 HTML 作为树节点文本,而不仅仅是纯文本。

image

18. 支持多行编辑模式

EnableMultiLineEdit 属性设置为 true 以启用此功能,默认值为 false

image

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 )",访问 演示

屏幕截图

image

20. ASTreeViewNode 的新属性 – EnableChildren

将此属性设置为 false 可以禁止将其他节点拖放到当前节点作为子节点。请参考 示例 1 查看效果。

21. 垂直拖放节点

如果您将 ASTreeView 用作列表,可以将 EnableHorizontalLock 设置为 true,这样最终用户只能上下移动节点,而不能左右移动。

屏幕截图

image

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。

屏幕截图

image

25. 支持自定义 JavaScript 处理程序

例如,如果开发人员希望在服务器返回指定条件时取消添加节点操作。他可以

  1. 设置 EnableOnNodeAddedScriptReturn="true"
  2. 设置 OnNodeAddedScript="addedHandler(elem)"
  3. 编写 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 将取消添加操作。

同样的方法也可以应用于编辑、删除和拖放。

一些截图

image

image

26. 新增 API (1.5.8)

1.5.8 版本新增 API

  • SelectNode – 按节点值选择节点
  • CheckNodes – 按节点值选中节点
  • UnCheckNodes - 按节点值取消选中节点
  • FindByValue – 按节点值查找节点,类似于 WebControl 中的 FindControl
  • FindByText – 按节点文本查找节点

27. ASDropDownTreeView 中的启用/禁用功能

开发人员现在可以设置 ASDropDownTreeViewEnabled 属性来启用/禁用它。

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 版本中,添加了若干新功能

  1. 新增 API
  2. ASDropDownTreeView 中的启用/禁用功能
  3. ASTreeViewNode 的 EnableOpenClose 属性
  4. [重要] 拖放 API 更改

在 1.5.5 版本中,添加了若干新功能

  1. 为检查、选择和查找节点添加了新 API:SelectNodeCheckNodesUnCheckNodesFindByValueFindByText
  2. 添加了新的节点类型:TextNode
  3. 添加了 EnableDragDropOnIcon 属性
  4. 支持自定义 JavaScript 处理程序
  5. 改进了 ASTreeView 的 CSS
  6. 改进了 ViewState 管理
  7. 强命名程序集

在 1.4.0 版本中,添加了若干新功能

  1. 垂直拖放节点
  2. 修复拖放深度
  3. 添加 OnNodeDragAndDropStartScript 事件
  4. 修复了若干 bug

在 1.3.0 版本中,添加了若干新功能

  1. 主题
  2. 从右到左支持
  3. 支持将 HTML 作为 TreeNodeText
  4. 支持转义编辑/添加输入
  5. 支持多行编辑模式
  6. 拖放完成事件现已可用
  7. ASTreeViewNode 的新属性 – EnableChildren
© . All rights reserved.