1、一般而言,如果想給aspx頁面上的web form control加上一些javascript的特性,可以用Attributes.Add來實現。
例如,對TextBox txt,可以:
txt.Attributes.Add("onclick", "fcn0();");
那麼,在web頁面上click它的時候,就會調用fcn0這個javascript函數。
1.1、例外的情況是,對於IDE無法辨認的屬性的解析。
比如對一個RadioButton rbt,IDE不能辨認onclick這個屬性,那麼,類似上面的語句,
rbt.Attributes.Add("onclick", "fcn1(this);");
在.net framework 1.1中,將解析成
<input type=radio id=rbt onclick="fcn1(this);">...
而在在.net framework 1.0中,將解析成
<span onclick="fcn1(this);"><input type=radio id=rbt>...</span>
注意到,fcn1中,參數this對應的對象就不同了。這是一個細微的差別。
2、而對於HTML control,需要多做一點事情。
在設計aspx頁面的時候,從工具列拖一個web form control,比如說,TextBox到頁面,會發生兩件事:
一、aspx頁面多一句
<asp:TextBox id="TextBox1" style="..." runat="server" Width="102px" Height="25px"></asp:TextBox>
二、code behind多一句
protected System.Web.UI.WebControls.TextBox TextBox1;
如果是html control,那麼,第一句中,runat="server"不會出現,而第二局不會被自動添加。
因此,如果要訪問html control,需要
一、aspx頁面的語句中添加runat="server"屬性,成為
<INPUT style="..." type="text" size="9" id="htxt" runat="server">
二、code behind中顯示的聲明
protected System.Web.UI.HtmlControls.HtmlInputText htxt;
注意到第一句的id和第二句的變數名是相同的。
2.1、注意到,前面System.Web.UI.WebControls.TextBox對應的html control是System.Web.UI.HtmlControls.HtmlInputText,對應的html的tag是<INPUT type="text">,
相應的,html的tag <body>對應的html control是
public System.Web.UI.HtmlControls.HtmlGenericControl myBody;
2.2、有一點例外的是html的<form> tag對應的onsubmit的事件。看這樣一個aspx頁面
<%@ Page language="c#" Codebehind="WebForm2.aspx.cs" AutoEventWireup="false" Inherits="TestCs.WebForm2" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm2</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
<script language="javascript">
function fcn1()
{
prompt("hi", "fcn1");
}
</script>
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="WebForm2" method="post" runat="server" onsubmit="fcn1();">
<asp:Button id="Button1" style="Z-INDEX: 103; LEFT: 423px; POSITION: absolute; TOP: 83px" runat="server" Width="86px" Height="29px" Text="Button"></asp:Button>
<asp:DropDownList id="DropDownList1" style="Z-INDEX: 104; LEFT: 284px; POSITION: absolute; TOP: 163px" runat="server" Width="188px" Height="17px" AutoPostBack="True">
<asp:ListItem Value="a">a</asp:ListItem>
<asp:ListItem Value="b">b</asp:ListItem>
<asp:ListItem Value="c">c</asp:ListItem>
</asp:DropDownList>
</form>
</body>
</HTML>
內容很簡單,定義了一個javascript函數fcn1,放了一個Button Button1和一個autopostback的Dropdownlist DropDownList1,運行它,可以看到:點擊Button1,會先執行fcn1然後postback,而選擇DropDownList1的不同選項,將只會postback,而不會觸發fcn1。
微軟autopostback=true的webcontrol實現postback,原理是這樣的:
一、如果此aspx頁面有autopostback=true的webcontrol,那麼會寫下面一段javascript語句定義一個叫__doPostBack的javascript函數。
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("netscape") > -1) {
theform = document.forms["WebForm2"];
}
else {
theform = document.WebForm2;
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
二、例如是上面的dropdownlist,將會render成:
<select name="DropDownList1" onchange="__doPostBack('DropDownList1','')" language="javascript" id="DropDownList1" style="...">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>
這樣,通過javscript調用theform.submit();來submit form,postback,但是,theform.submit將不會觸發form的onsubmit事件!
這是微軟的一個bug。
解決的方法可以看這裡:http://www.devhawk.net/art_submitfirefixup.ashx,這裡提供了一個dll及原始碼,使用的時候,在project的reference裡加入這個dll,然後在web.config中加上一段
<httpModules>
<add type="DevHawk.Web.SubmitFireFixupModule,SubmitFireFixupModule" name="SubmitFireFixupModule" />
</httpModules>
就可以了。
3、一個應用。
常常聽到抱怨,說如果在Browser端用javascript改動了某個<select>元素,那麼,它對應的Server端的DropDownList不能得知這個更新。
這種情況可能出現在“級聯”的DropDownList中,比如第一個DropDownList是省份,第二個是城市;也可能出現在,從第一個DropDownList選擇某些項加入到第二個DropDownList中。
對此使用以上的技術,我做了一個這樣的解決方案(類似於ViewState的方法):
一、我定義了一個長寬都是0的TextBox txtWrap,並把所有我想處理的DropDownList都加上AthosOsw="True" 這樣的屬性,準備處理。
二、參照上面2.2的內容,我加入了SubmitFireFixupModule,來保證觸發form的onsubmit事件。
三、form的onsubmit事件將執行javascript函數fcnAthosOnSubmitWrap,它將遍曆AthosOsw屬性為True的DropDownList,記下資料,最後合并起來放到txtWrap裡,其實這就是一個序列化的過程。代碼如下:
function fcnAthosOnSubmitWrap()
{
txtWrap = document.all["txtWrap"];
var i;
var strWrap = '';
for(i=0;i<document.all.length;i++)
{
ctrl = document.all[i];
if(ctrl.tagName.toUpperCase() == 'SELECT' && typeof(ctrl.AthosOsw) != 'undefined' )
{
if(ctrl.AthosOsw.toUpperCase() == 'TRUE')
{
strWrap += fcnAthosWrapSelect(ctrl) + '&&&';
}
}
}
if(strWrap.length>3)
txtWrap.value = strWrap.substring(0, strWrap.length-3);
};
//AthosOsw
function fcnAthosWrapSelect(ctrlSelect)
{
var i;
var strWrapSelect = ctrlSelect.id + '&' + ctrlSelect.tagName;
var strValue='';
var strText='';
for(i=0; i<ctrlSelect.options.length; i++)
{
strValue = ctrlSelect.options[i].value;
strText = ctrlSelect.options[i].text;
strWrapSelect += '&&' + i + '&' + strValue.replace(/&/g, '%26') + '&' + strText.replace(/&/g, '%26');
};
return strWrapSelect;
};
四、form的Page_Load中調用clsCommon.UnwrapControl(this, txtWrap.Text);來還原序列化。clsCommon是我的工具類,UnwrapControl方法代碼如下:
static public void UnwrapControl(System.Web.UI.Page pgUnwrap, String strUnwrap)
{
Regex r3 = new Regex("(&&&)"); // Split on hyphens.
Regex r2 = new Regex("(&&)"); // Split on hyphens.
Regex r1 = new Regex("(&)"); // Split on hyphens.
String[] sa3, sa2, sa1;
String s3, s2, s1;
int i3, i2, i1;
String strId, strTagName;
System.Web.UI.Control ctrlUnwrap;
DropDownList ddlUnwrap;
ListItem liAdd;
s3 = strUnwrap;
sa3 = r3.Split(s3);
for(i3=0;i3<(sa3.Length+1)/2;i3++)
{
s2 = sa3[i3*2];
if(s2.Length>0)
{
sa2 = r2.Split(s2);
if(sa2.Length>1)
{
s1 = sa2[0];
sa1 = r1.Split(s1);
if(sa1.Length==3)
{
strId = sa1[0];
strTagName = sa1[2];
ctrlUnwrap = pgUnwrap.FindControl(strId);
if(ctrlUnwrap !=null)
{
if(strTagName == "SELECT")
{
ddlUnwrap = (DropDownList)ctrlUnwrap;
ddlUnwrap.Items.Clear();
for(i2=1; i2 < (sa2.Length+1)/2;i2++)
{
s1 = sa2[i2*2];
sa1 = r1.Split(s1);
liAdd = new System.Web.UI.WebControls.ListItem(sa1[4],sa1[2]);
ddlUnwrap.Items.Add(liAdd);
}
}
}
}
}
}
}
}