前一阵子,有位仁兄问我:“怎么样得到点击某节点时击发一个返回服务器处理的事件?”我给了他以下函数,并告知他treeview的autopostback一定要打开(值为true):
private void treeview1_selectedindexchange(object sender, microsoft.web.ui.webcontrols.treeviewselecteventargs e)
{
treenode node=new treenode();
node=treeview1.getnodefromindex(treeview1.selectednodeindex);
string sindex;
sindex = treeview1.selectednodeindex;
if (sindex.indexof(".")>=0 )
{
sindex = sindex.substring(0,sindex.lastindexof("."));
}
inittree(node,sindex);
}
事后,没几天,他又问:“为什么点击已经选过的节点没有反应?怎么解决?急急急………..”
其实这是treeview的一个bug,selectedindexchange是节点索引的改变事件,如果某个节点已经被选中,那它就不能触发该事件,那怎么解决呢?
我们来看看treeview控件在前台生成的代码吧:
<tvns:treeview id="treeview1" selectedstyle="background-color:blue;" selectednodeindex="0" helperid="__treeview1_state__" systemimagespath="/webctrl_client/1_0/treeimages/" onexpand="javascript: if (this.clickednodeindex != null) this.queueevent(onexpand, this.clickednodeindex)" oncollapse="javascript: if (this.clickednodeindex != null) this.queueevent(oncollapse, this.clickednodeindex)" oncheck="javascript: if (this.clickednodeindex != null) this.queueevent(oncheck, this.clickednodeindex)" onselectedindexchange="javascript: if (event.oldtreenodeindex != event.newtreenodeindex) this.queueevent(onselectedindexchange, event.oldtreenodeindex + , + event.newtreenodeindex)" onfirequeuedevents="javascript: window.settimeout(__dopostback(\treeview1\,\\), 0, javascript)" style="background-color:yellowgreen;height:362px;width:112px;">
其中有一个触发该事件的函数就是queueevent(,),看到触发条件没有:if (event.oldtreenodeindex != event.newtreenodeindex),我们现在是(event.oldtreenodeindex == event.newtreenodeindex),怎么办?
别急,我们自己给它加上一个onclick事件来调用该函数就ok了,注意里面的参数也要变喔,否则会出错滴。看看我的代码先:
在后台page_load区加入:
treeview1.attributes["onclick"] = "javascript: if(this.clickednodeindex != null)this.queueevent(onselectedindexchange, + , + this.clickednodeindex)";
强调:其中的if(this.clickednodeindex != null)要有,否则你点在treeview除节点以外的地方一样会触发该事件,而函数会找不到节点的索引值的。
深入探讨:
.net的后台代码经服务器编译后发送到客户端,生成相应的脚本,它的返回都是靠前台事件启动的,来让我们看看它在前台都生成了什么。
<input type="hidden" name="__eventtarget" value="" />
<input type="hidden" name="__eventargument" value="" />
<script language="javascript">
<!–
function __dopostback(eventtarget, eventargument) {
var theform;
if (window.navigator.appname.tolowercase().indexof("netscape") > -1) {
theform = document.forms["form1"];
}
else {
theform = document.form1;
}
theform.__eventtarget.value = eventtarget.split("$").join(":");
theform.__eventargument.value = eventargument;
theform.submit();
}
// –>
</script>
看到没有,它生成了两个隐藏的input,它是用来干什么的呢?告诉你吧,它们一个是用来暂存触发事件的控件的id的,另一个则是用来暂存触发时的参数的,前台事件会把这两个参数传给__dopostback()函数,而真正起作用的正是这个__dopostback()函数,如果我们自己给它加上一个调用的事件,比如:textbox1.attributes["onclick"] = "__dopostback(button1,)",那它不仅可以返回服务器处理,还能调用其它控件的特有函数呢。这样你能做些什么改变自己去想想吧,不过我要说明一点,这个__dopostback()函数不是每次后台编译都生成,拉出一个treeview或者datagrid它就会有,如果没有也不用急,我们可以在后台添加它。
