表单,英文单词是Form,学习过VB的朋友一定不会陌生。在MS.NET架构里,Form是一个经常使用到的词汇。比如:编写Windows 应用时会提到Windows Form,编写Web 应用时会提到Web Form。Windows Form可以看作一个Windows窗体,这和在VB里面一样。而Web Form则代表了一个一个的Web页面。总的看来,Form就像是一个容纳各种控件的容器,各种控件都必须直接或者间接的和它有依存关系。Form在这里译作"WEB表单"似乎有些不妥。"表单"这个词,在WEB程序员看来,总是和HTML里面的"Form"相混淆。"WEB表单"似乎翻译成"WEB页面"更加妥当一些。
大家还记得VB里面的Form实际上就是一个对象吧,它可以有自己的属性、方法、事件等等。WEB表单,或者说WEB页面,实际上是一个"对象" (Object)。MS.NET架构里面一个比较重要的概念就是"对象":所有的控件都是对象,甚至数据类型都成了对象;每种数据类型都有自己特有的属性和方法。我们在后面的编程中将可以体会到。
WEB FORM的后缀名是ASPX。当一个浏览器第一次请求一个ASPX文件时,WEB FORM页面将被CLR(common language runtime)编译器编译。此后,当再有用户访问此页面的时候,由于ASPX页面已经被编译过,所以,CLR会直接执行编译过的代码。这和ASP的情况完全不同。ASP只支持VBScript和JavaScript这样的解释性的脚本语言。所以ASP页面是解释执行的。当用户发出请求后,无论是第一次,还是第一千次,ASP的页面都将被动态解释执行。而asp.net支持可编译的语言,包括VB.NET、C#、Jscript.NET等。所以,asp.net是一次编译多次执行。
为了简化程序员的工作,ASPX页面不需要手工编译,而是在页面被调用的时候,由CLR自行决定是否编译。一般来说,下面两种情况下,ASPX会被重新编译:
1.ASPX页面第一次被浏览器请求;
2.ASPX被改写
由于ASPX页面可以被编译,所以ASPX页面具有组件一样的性能。这就使得ASPX页面至少比同样功能的ASP页面快250%!
下面我们来看一下简单的WEB页面。
我的第一个Page
把下面的代码拷贝到myfirstpage.aspx文件中,然后从浏览器访问这个文件:
<!--源文件:form\web页面简介\myfirstpage.aspx-->
<form action="myfirstpage.aspx" method="post">
<h3> 姓名: <input id="name" type=text>
所在城市: <select id="city" size=1>
<option>北京</option>
<option>上海</option>
<option>重庆</option>
</select>
<input type=submit value="查询">
</form>
你可能觉得这个页面太简单了,用HTML就可以完成。是的!微软建议你将所有的文件哪怕是纯HTML文件都保存为ASPX文件后缀,这样可以加快页面的访问效率!不仅仅是在asp.net环境中,在IIS5.0以后的ASP3.0就已经支持这个特性了。
由于我们没有对表单提交做任何响应,所以,当你按下"查询"按钮,页面的内容没有什么改变。
下面我们将逐步使用asp.net的思考方式,来完成我们的页面。
WEB页面处理过程
这一节我们将深入到asp.net内部,看看页面是怎样被处理的。
和所有的服务器端进程一样,当ASPX页面被客户端请求时,页面的服务器端代码被执行,执行结果被送回到浏览器端。这一点和ASP并没有太大的不同。
但是,asp.net的架构为我们做了许多别的事情。比如,它会自动处理浏览器的表单提交,把各个表单域的输入值变成对象的属性,使得我们可以像访问对象属性那样来访问客户的输入。它还把客户的点击映射到不同的服务器端事件。
了解WEB页面的处理过程很重要。这样你可以仔细地优化你的代码,提高代码的效率。
页面的一次往返处理
用户对Server Control的一次操作,就可能引起页面的一次往返处理:页面被提交到服务器端,执行响应的事件处理代码,重建页面,然后返回到客户端。
正因为每个Control都可能引发一次页面的服务器端事件,所以,asp.net尽量减少了控件的事件类型。很多组件都只有OnClick事件。特别的,asp.net不支持服务器端的OnMouseOver事件。因为OnMouseOver事件发生得非常频繁。所以,支持服务器端的OnMouseOver事件是非常不现实的。
页面重建
每一次页面被请求,或者页面事件被提交到服务器,asp.net运行环境将执行必要的代码,重建整个页面,把结果页面送到浏览器,然后抛弃页面的变量、控件的状态和属性等等页面信息。当下一次页面被处理时,asp.net运行环境是不知道它的上一次执行情况的。在这个意义上,ASPX页面是没有状态的。这也是HTTP协议的特点(为了加速页面的访问,在asp.net页面里面可以使用缓存机制,也就是保存页面的执行结果,下一次页面被请求时,直接送回上一次的执行结果。)。
在ASP中,当页面被提交到服务器端时,只有那些用户输入的值被传递到服务器。其他的比如组件的属性、变量的值,是不会传递的。所以服务器无法了解组件的进一步的信息。
在asp.net中,页面对象的属性、页面控件的属性被称为"view state"(页面状态)。页面状态在asp.net中被受到特别关照。请看服务器端(page1.aspx)的代码:
<!--源文件:form\web页面简介\page1.aspx-->
<HTML>
<BODY>
<SCRIPT language="VB" runat="server">
Sub ShowValues(Sender As Object, Args As EventArgs)
divResult.innerText = "You selected '" _
& selOpSys.value & "' for machine '" _
& txtName.value & "'."
End Sub
</SCRIPT>
<DIV id="divResult" runat="server">
</DIV>
<FORM runat="server">
机器名:
<INPUT type="text" id="txtName" runat="server">
<P />
操作系统:
<select id="selOpSys" size="1" runat="server">
<OPTION>Windows 95</OPTION>
<OPTION>Windows 98</OPTION>
<OPTION>Windows NT4</OPTION>
<OPTION>Windows 2000</OPTION>
</SELECT>
<P />
<INPUT type="submit" value="Submit" runat="server" onserverclick="ShowValues">
</FORM>
</BODY>
</HTML>
运行后将自动被解释成客户端代码,如下:
<HTML>
<BODY>
You selected 'Windows 98' for machine 'iceberg'.
<FORM name="ctrl0" method="post" action="pageone.aspx" id="ctrl0">
<INPUT type="hidden" name="__VIEWSTATE" value="a0z1741688109__x">
机器名:
<INPUT type="text" id="txtName" name="txtName" value="tizzy">
<P />
操作系统:
<SELECT id="selOpSys" size="1" name="selOpSys">
<OPTION value="Windows 95">Windows 95</OPTION>
<OPTION selected value="Windows 98">Windows 98</OPTION>
<OPTION value="Windows NT4">Windows NT4</OPTION>
<OPTION value="Windows 2000">Windows 2000</OPTION>
</SELECT>
<P />
<INPUT type="submit" value="Submit">
</FORM>
</BODY>
</HTML>
对于上面的代码,服务器端控件能在服务器端脚本中被自由运用。如果我们用传统的ASP代码实现上述的功能的话:
If Len(Request.Form("selOpSys")) > 0 Then
StrOpSys = Request.Form("selOpSys")
StrName = Request.Form("txtName")
Response.Write("You selected '" & strOpSys _
& "' for machine '" & strName & "'.")
End If
如果我们用asp.net的话,程序代码如下:
If Len(selOpSys.value) > 0 Then
Response.Write("You selected '" & selOpSys.value _
& "' for machine '" & txtName.value & "'.")
End If
通过上面例子不难看出:asp.net页面具有组件方式的方便性和灵活性。
请注意:asp.net通过把页面的状态封装到一个隐藏的输入域,从而可以在不同的页面之间实现传递页面的状态。
另外,asp.net也支持应用程序一级的状态管理。这个特性在ASP中就已经实现。
页面处理内部过程
我们来看看页面处理的内部过程。下面的过程是依次进行的:
Page_load
首先,页面的状态被恢复,然后触发Page_OnLoad事件。在这个过程中,你可以读取或者重置页面的属性和控件的属性,根据IsPostBack属性判定页面是否为第一次被请求,执行数据绑定,等等。
现在我们通过一个具体的例子,来详细讲述Page_load事件:
我们所做的这个例子关于用户登录的。
我们先来看page.aspx的代码:
<!--源文件:form\web页面简介\page.aspx-->
<%@ Register TagPrefix="Acme" TagName="Login" Src="page.ascx" %>
<html>
<title>登录演示</title>
<script language="VB" runat="server">
Sub Page_Load(Sender As Object, E As EventArgs)
If (Page.IsPostBack)
MyLabel.Text &= "用户名:" & MyLogin.UserId & "<br>"
MyLabel.Text &= "密码: " & MyLogin.Password & "<br>"
End If
End Sub
</script>
<body style="font: 10pt verdana">
<center> <h3>登录</h3></center>
<form runat="server">
<Acme:Login id="MyLogin" UserId="" Password="" BackColor="beige" runat="server"/>
</form>
<asp:Label id="MyLabel" runat="server"/>
</body>
</html>
在这个文件中,我们使用了Page_OnLoad事件的IsPostBack属性,用来显示用户登录时的用户名和密码。
在来看一下page.ascx文件:
<!--源文件:form\web页面简介\page.ascx-->
<script language="VB" runat="server">
Public BackColor As String = "white"
Public Property UserId As String
Get
Return UserName.Text
End Get
Set
UserName.Text = Value
End Set
End Property
Public Property Password As String
Get
Return Pass.Text
End Get
Set
Pass.Text = Value
End Set
End Property
</script>
<center>
<table style="background-color:<%=BackColor%>;font: 10pt verdana;border-width:1;
border-style:solid;border-color:black;" cellspacing=15>
<tr>
<td><b>用户名: </b></td>
<td><ASP:TextBox id="UserName" runat="server"/></td>
</tr>
<tr>
<td><b>密码: </b></td>
<td><ASP:TextBox id="Pass" TextMode="Password" runat="server"/></td>
</tr>
<tr>
<td></td>
<td><ASP:Button Text="提交" runat="server"/></td>
</tr>
</table>
</center>
在这个文件中,我们设置了控件的属性。使之能在page.aspx中调用程序的运行如图:
在下一个例子中,我们将使用Page_OnLoad事件,来执行数据绑定:
文件databind.aspx代码如下:
<!--源文件:form\web页面简介\databind.aspx-->
<html>
<head>
<title>数据绑定演示</title>
<script language="VB" runat="server">
Sub Page_Load(sender As Object, e As EventArgs)
If Not IsPostBack Then
Dim values as ArrayList= new ArrayList()
values.Add ("北京")
values.Add ("上海")
values.Add ("杭州")
values.Add ("成都")
values.Add ("重庆")
values.Add ("西安")
DropDown1.DataSource = values
DropDown1.DataBind
End If
End Sub
'定义按钮的单击事件
Sub SubmitBtn_Click(sender As Object, e As EventArgs)
'结果显示
Label1.Text = "你选择的城市是: " + DropDown1.SelectedItem.Text
End Sub
</script>
</head>
<body>
<center><h3><font face="Verdana">数据绑定演示</font></h3></center>
<form runat=server>
<center><asp:DropDownList id="DropDown1" runat="server" /></center>
<center><asp:button Text="提交" OnClick="SubmitBtn_Click" runat=server/></center>
<p>
<center><asp:Label id=Label1 font-name="Verdana" font-size="10pt" runat="server" /></center>
</form>
<body>
</html>
程序运行效果如图:
当我们点击"提交"按钮时:
在下面的例子中,我们将用page_load事件来对数据库进行连接:
我们还要说明的是如果使用SQL语句对数据库进行操作的时候,就需要在页面中导入System.Data 和 System.Data.SQL 名字控件,文件pagedata.aspx的代码如下:
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SQL" %>
程序代码如下(pagedata.aspx):
<!--源文件:form\web页面简介\pagedata.aspx-->
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SQL" %>
<html>
<script language="VB" runat="server">
Sub Page_Load(Src As Object, E As EventArgs)
Dim DS As DataSet
Dim MyConnection As SQLConnection
Dim MyCommand As SQLDataSetCommand
'同数据库进行连接,采用sql server数据库
MyConnection = New SQLConnection("server='iceberg';uid=sa;pwd=;database=info")
'执行SQL操作
MyCommand = New SQLDataSetCommand("select * from infor",MyConnection)
DS = New DataSet()
MyCommand.FillDataSet(ds, "infor")
MyDataGrid.DataSource=ds.Tables("infor").DefaultView
MyDataGrid.DataBind()
End Sub
</script>
<center>
<body>
<h3><font face="Verdana">Page_load事件演示</font></h3>
<ASP:DataGrid id="MyDataGrid" runat="server"
Width="600"
BackColor="white"
BorderColor="black"
ShowFooter="false"
CellPadding=3
CellSpacing="0"
Font-Name="Verdana"
Font-Size="8pt"
HeaderStyle-BackColor="#aaaadd"
MaintainState="false"
/>
/body>
</center>
</html>
在这个程序中,我们在page_load事件中,我们做了哪些事呢?
① 与数据库连接。在这个例子中,我们使用SQL Server作为后台数据库。在这个库中,我们建立了info数据库,在数据库中有一张infor表。
② 执行SQL操作
③ 将筛选后的数据显示出来
我们再来看看程序运行的效果:
上面就是对Page_load事件的介绍,相信大家通过例子能对该事件有个理解。
事件处理
这一阶段处理表单的事件。你可以处理特定的事件,也可以在表单需要校验的情况下,根据IsValid属性判定页面的输入是否有效。
Web Form提供了一些具有验证功能的服务器控件。这些控件提供了一套简单易用并且很强大的功能能检查输入时是否有错误。而且,还能显示提示信息给用户。
对于每个控件来说,都有一特定的属性,来验证输入的值是否有效。我们来看一下对输入控件需要验证的属性:
控件 | 需要验证的属性 |
HtmlInputText | Value |
HtmlTextAreaHtm | Value |
HtmlSelect | Value |
HtmlInputFile | Value |
TextBox | Text |
ListBox | SelectedItem |
DropDownList | SelectedItem |
RadioButtonList | SelectedItem |
好了,有了上面的介绍,我们就以例子来讲解表单的有效性验证。
在下面一个简单的例子中,我们将对用户的输入验证。
如Validate.aspx 的内容如下:
<!--源文件:form\web页面简介\validate.aspx-->
<html>
<head>
<script language="VB" runat="server">
Sub ValidateBtn_Click(sender As Object, e As EventArgs)
If (Page.IsValid) Then
lblOutput.Text = "页面有效!"
Else
lblOutput.Text = "在页面中不能出现空项!"
End If
'判断是否输入为数字
if not isnumeric(TextBox1.text) then
lbloutput.text="请输入数值!"
End if
End Sub
</script>
</head>
<body>
<center><h3><font face="Verdana">验证表单的例子</font></h3></center>
<p>
<form runat="server">
<title>表单验证</title>
<center>
<table bgcolor="white" cellpadding=10>
<tr >
<td colspan=3>
<asp:Label ID="lblOutput" Text="请填写下面的内容" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat=server /><br>
</td>
</tr>
<tr>
<td align=right>
<font face=Verdana size=2>储蓄卡类型:</font>
</td>
<td>
<ASP:RadioButtonList id=RadioButtonList1 RepeatLayout="Flow" runat=server>
<asp:ListItem>绿卡</asp:ListItem>
<asp:ListItem>牡丹卡</asp:ListItem>
</ASP:RadioButtonList>
</td>
<td align=middle rowspan=1>
<asp:RequiredFieldValidator id="RequiredFieldValidator1"
ControlToValidate="RadioButtonList1"
Display="Static"
InitialValue="" Width="100%" runat=server>
*
</asp:RequiredFieldValidator>
</td>
</tr>
<tr>
<td align=right>
<font face=Verdana size=2>卡号:</font>
</td>
<td>
<ASP:TextBox id=TextBox1 runat=server />
</td>
<td>
<asp:RequiredFieldValidator id="RequiredFieldValidator2"
ControlToValidate="TextBox1"
Display="Static"
Width="100%" runat=server>
*
</asp:RequiredFieldValidator>
</td>
</tr>
<td>
</tr>
<tr>
<td></td>
<td>
<ASP:Button id=Button1 text="验证" OnClick="ValidateBtn_Click" runat=server />
</td>
<td></td>
</tr>
</table>
</center>
</form>
</body>
</html>
我们对验证按钮的OnClick事件进行编程,其中用到了IsNumeric()函数,用来判断变量是否为数值型的。我们还可以用IsData()函数对输入的日期进行判断。IsData()接受的合法日期为100年1月1日到9999年12月31日。
运行如图:
当我们在卡号一栏中输入一些字母,而不是数值时,页面上将会提示你输入数值。
让我们再举一个很有用的验证应用:
当用户在填写个人信息的时候,往往需要输入身份证号,那么我们是如何进行身份证号的验证呢?
要解决这个问题,首先,让我们先看看我国的身份证号是如何编码的。
1 2 3 4 5
XX XXXX XXXXXX XX X (这个是没有升位以前的一个身份证号码的组成方式)
1 省 2 地市 3 生日 4 顺序码 5 性别
在这个例子中,我们只对省份进行判断。
身份编码一览表:
北京 | 吉林 22 | 福建 35 | 广东 44 | 云南 53 |
天津 12 | 黑龙江 23 | 江西 36 | 广西 45 | 西藏 54 |
河北 13 | 上海 31 | 山东 37 | 海南 46 | 陕西 61 |
山西 14 | 江苏 32 | 河南 41 | 重庆 50 | 甘肃 62 |
内蒙古 15 | 浙江 33 | 湖北 42 | 四川 51 | 青海 63 |
辽宁 21 | 安徽 34 | 湖南 43 | 贵州 52 | 宁夏 64 |
新疆 65 | 台湾 71 | 香港 81 | 澳门 82 | 国外 91 |
在这个程序中,仅仅作了一个简单的判断
Validate1.aspx的文件内容如下:
<!--源文件:form\web页面简介\validate1.aspx-->
<html>
<head>
<script language="VB" runat="server">
Sub ValidateBtn_Click(sender As Object, e As EventArgs)
If (Page.IsValid) Then
lblOutput.Text = "页面有效!"
Else
lblOutput.Text = "在页面中不能出现空项!"
End If
If not isnumeric(TextBox1.text) then
bloutput.text="请输入数值!"
End if
'在这里我们只作了一个简单的判断。使用了left$()函数
if left$(textbox1.text,2)<>"11" then
lbloutput.text="请验证你的身份证输入"
End if
End Sub
</script>
</head>
<body>
<center><h3><font face="Verdana">验证表单的例子</font></h3></center>
<p>
<form runat="server">
<title>表单验证</title>
<center>
<table bgcolor="white" cellpadding=10>
<tr >
<td colspan=3>
<asp:Label ID="lblOutput" Text="请填写下面的内容" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat=server /><br>
</td>
</tr>
<tr>
<td align=right>
<font face=Verdana size=2>身份证号:</font>
</td>
<td>
<ASP:TextBox id=TextBox1 runat=server />
</td>
<td>
<asp:RequiredFieldValidator id="RequiredFieldValidator2"
ControlToValidate="TextBox1"
Display="Static"
Width="100%" runat=server>
*
</asp:RequiredFieldValidator>
</td>
</tr>
<td>
</tr>
<tr>
<td></td>
<td>
<ASP:Button id=Button1 text="验证" OnClick="ValidateBtn_Click" runat=server />
</td>
<td></td>
</tr>
</table>
</center>
</form>
</body>
</html>
在这个程序中,我们仅对北京地区的身份证号进行了验证,我们使用Left$()函数把字符串的前两个字符取出进行比较。如果大家感兴趣的话,可以把这个程序补充完整。
程序的运行如图:
这是输入正确的情况,如输入不正确,则显示(如图):