今天 优快云 有一网友提出这样的需求:
实现点击 TreeView 的 CheckBox 即自动 PostBack
http://community.youkuaiyun.com/Expert/TopicView3.asp?id=5708685
解决方案可以考虑:
1. 在客户端手动通过 js 捕获 checkbox 的 click 事件,然后显示的执行 __doPostBack 方法
对于如何捕获事件,获取目标节点,与 类似 TreeView几个小技巧 提到的 父子节点CheckBox的级联选择 类似
2. 扩展 TreeNode(继承 System.Web.UI.WebControls.TreeNode)
然而 TreeNode 并未继承自 System.Web.UI.Control,故而无法访问 checkbox 自控件,其无 Render 之类的方法。虽然它对控件开发者提供了 RenderPreText 和 RenderPostText 方法,分别在节点前、后添加自定义信息,但还是无法访问 CheckBox。
看来此路暂时不通
3. 扩展 TreeView,重写 Render,通过 HtmlTextWriter 获取呈现的 html 代码,并想办法遍历其中的 <input type=checkbox /> 为其添加 οnclick=_doPostBack
经测试此法,我看行
XTreeView.cs
using
System;
using
System.Data;
using
System.Configuration;
using
System.IO;
using
System.Text;
using
System.Text.RegularExpressions;
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.Xml;

namespace
Digdotnet.Test

{

/**//// <summary>
/// XTreeView 的摘要说明
/// </summary>
public class XTreeView : TreeView

{

/**//// <summary>
/// 为 checkbox 添加客户端事件 click 处理程序。
/// <remarks>
///
/// 默认 TreeView 节点呈现为
/// <input type="checkbox" name="TreeView1n2CheckBox" id="TreeView1n2CheckBox" title="1.1.1" />
/// <a class="TreeView1_0" href="javascript:__doPostBack('TreeView1','s1//1.1//1.1.1')" οnclick="TreeView_SelectNode(TreeView1_Data, this,'TreeView1t2');" id="TreeView1t2">1.1.1</a>
///
/// 重写 Render 方法之后呈现为
/// <input type="checkbox" name="TreeView1n2CheckBox" id="TreeView1n2CheckBox" οnclick="TreeView_SelectNode(TreeView1_Data, this.nextSibling,'TreeView1t2');__doPostBack('TreeView1','s1//1.1//1.1.1')" title="1.1.1" />
/// <a class="TreeView1_0" href="javascript:__doPostBack('TreeView1','s1//1.1//1.1.1')" οnclick="TreeView_SelectNode(TreeView1_Data, this,'TreeView1t2');" id="TreeView1t2">1.1.1</a>
///
/// </remarks>
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)

{

if (DesignMode)
{ // 设计时,不做处理
base.Render(writer);
return;
}

//
StringWriter sw = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(sw);
// 输出 TreeView 的 html 源码
base.Render(htmlWriter);
//
sw.Flush();
string treeHtml = sw.ToString();

// 从节点的 <a/> 标记中分析 href 和 onclick 属性中的两个 js 函数,
// 并插入 checkbox 的 onclick 事件
string pattern = @"<input.* (id=.*) title=.*/>[/n/r/s]*<a.* href=.*(__doPostBack.*)"".* οnclick=.*(TreeView_SelectNode.*);"".* id=.*"">";
Match match = Regex.Match(treeHtml, pattern);
// 正则替换
treeHtml = Regex.Replace(treeHtml, pattern, new MatchEvaluator(ReplaceTextCallback));

// 呈现经过处理的 TreeView
writer = new HtmlTextWriter(Context.Response.Output);
writer.Write(treeHtml);
}


/**//// <summary>
/// 正则替换回调方法。
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
private static string ReplaceTextCallback(Match match)

{
int pos = match.Value.IndexOf(match.Groups[1].Value) + match.Groups[1].Value.Length + 1;
return match.Value.Insert(pos, String.Format(@"οnclick=""{0};{1}"" ", match.Groups[3].Value.Replace("this", "this.nextSibling"), match.Groups[2].Value));
}
}
}
<%
@ Page Language="C#"
%>

<%
@ Register TagPrefix="ddntest" Namespace="Digdotnet.Test"
%>

<!
DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
>


<
script
runat
="server"
>

protected void TreeView1_TreeNodeCheckChanged(object sender, TreeNodeEventArgs e)

{
Label1.Text = String.Format("You check the node whose <font color='red'>Text={0} and ValuePath={1}</font>", e.Node.Text, e.Node.ValuePath);
}
</
script
>

<
html
xmlns
="http://www.w3.org/1999/xhtml"
>
<
head
runat
="server"
>
<
title
>
扩展 TreeView 实现选择 CheckBox 自动回发
</
title
>
</
head
>
<
body
>
<
form
id
="form1"
runat
="server"
>
<
div
>
<
h1
>
扩展 TreeView 实现选择 CheckBox 自动回发
</
h1
>
<
input
type
="button"
value
="Refresh"
onclick
="location.href=location.href"
/>
<
ddntest:XTreeView
id
="TreeView1"
runat
="server"
ShowCheckBoxes
="All"
OnTreeNodeCheckChanged
="TreeView1_TreeNodeCheckChanged"
>
<
Nodes
>
<
asp:TreeNode
Text
="1"
>
<
asp:TreeNode
Text
="1.1"
>
<
asp:TreeNode
Text
="1.1.1"
></
asp:TreeNode
>
</
asp:TreeNode
>
</
asp:TreeNode
>
<
asp:TreeNode
Text
="2"
>
<
asp:TreeNode
Text
="2.1"
>
<
asp:TreeNode
Text
="2.2.1"
></
asp:TreeNode
>
</
asp:TreeNode
>
</
asp:TreeNode
>
</
Nodes
>
</
ddntest:XTreeView
>
<
asp:Label
ID
="Label1"
runat
="server"
></
asp:Label
>
</
div
>
</
form
>
</
body
>
</
html
>
http://community.youkuaiyun.com/Expert/TopicView3.asp?id=5708685
解决方案可以考虑:
1. 在客户端手动通过 js 捕获 checkbox 的 click 事件,然后显示的执行 __doPostBack 方法
对于如何捕获事件,获取目标节点,与 类似 TreeView几个小技巧 提到的 父子节点CheckBox的级联选择 类似
2. 扩展 TreeNode(继承 System.Web.UI.WebControls.TreeNode)
然而 TreeNode 并未继承自 System.Web.UI.Control,故而无法访问 checkbox 自控件,其无 Render 之类的方法。虽然它对控件开发者提供了 RenderPreText 和 RenderPostText 方法,分别在节点前、后添加自定义信息,但还是无法访问 CheckBox。
看来此路暂时不通

3. 扩展 TreeView,重写 Render,通过 HtmlTextWriter 获取呈现的 html 代码,并想办法遍历其中的 <input type=checkbox /> 为其添加 οnclick=_doPostBack
经测试此法,我看行

XTreeView.cs

























































































测试页面


















































测试效果
BTW,对于 AJAX 大肆流行的今天, PostBack 似乎大家都敬而远之,是否需要此功能,还是看个人应用实际需求了。