扩展 TreeView 实现选择 CheckBox 自动回发
天**** 有一网友提出这样的需求:实现点击 TreeView 的 CheckBox 即自动 PostBack
http://community.****.net/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 /> 为其添加 onclick=_doPostBack
经测试此法,我看行
XTreeView.cs
usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.IO;
usingSystem.Text;
usingSystem.Text.RegularExpressions;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingSystem.Xml;

namespaceDigdotnet.Test


{

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


{

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


{

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

//
StringWritersw=newStringWriter();
HtmlTextWriterhtmlWriter=newHtmlTextWriter(sw);
//输出TreeView的html源码
base.Render(htmlWriter);
//
sw.Flush();
stringtreeHtml=sw.ToString();

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

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


/**////<summary>
///正则替换回调方法。
///</summary>
///<paramname="match"></param>
///<returns></returns>
privatestaticstringReplaceTextCallback(Matchmatch)


{
intpos=match.Value.IndexOf(match.Groups[1].Value)+match.Groups[1].Value.Length+1;
returnmatch.Value.Insert(pos,String.Format(@"onclick=""{0};{1}""",match.Groups[3].Value.Replace("this","this.nextSibling"),match.Groups[2].Value));
}
}
}

<%
@PageLanguage="C#"%>

<%
@RegisterTagPrefix="ddntest"Namespace="Digdotnet.Test"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<scriptrunat="server">

protectedvoidTreeView1_TreeNodeCheckChanged(objectsender,TreeNodeEventArgse)


{
Label1.Text=String.Format("Youcheckthenodewhose<fontcolor='red'>Text={0}andValuePath={1}</font>",e.Node.Text,e.Node.ValuePath);
}
</script>

<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>扩展TreeView实现选择CheckBox自动回发</title>
</head>
<body>
<formid="form1"runat="server">
<div>
<h1>扩展TreeView实现选择CheckBox自动回发</h1>
<inputtype="button"value="Refresh"onclick="location.href=location.href"/>
<ddntest:XTreeViewid="TreeView1"runat="server"ShowCheckBoxes="All"OnTreeNodeCheckChanged="TreeView1_TreeNodeCheckChanged">
<Nodes>
<asp:TreeNodeText="1">
<asp:TreeNodeText="1.1">
<asp:TreeNodeText="1.1.1"></asp:TreeNode>
</asp:TreeNode>
</asp:TreeNode>
<asp:TreeNodeText="2">
<asp:TreeNodeText="2.1">
<asp:TreeNodeText="2.2.1"></asp:TreeNode>
</asp:TreeNode>
</asp:TreeNode>
</Nodes>
</ddntest:XTreeView>
<asp:LabelID="Label1"runat="server"></asp:Label>
</div>
</form>
</body>
</html>
http://community.****.net/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 /> 为其添加 onclick=_doPostBack
经测试此法,我看行
XTreeView.cs
测试页面
测试效果
BTW,对于 AJAX 大肆流行的今天, PostBack 似乎大家都敬而远之,是否需要此功能,还是看个人应用实际需求了。