asp.net夜话之六:asp.net基本控件

Author: 周金桥

在本系列之三《asp.net 夜话之三:表单和控件》中讲到了HTML 服务器控件,HTML 服务器控件有如下特点:
(1 )HTML 服务器控件是建立在HTML 控件的基础上,额外增加了一个在当前页面中唯一的ID 属性值和一个runat=”server” 属性;
(2 )HTML 服务器控件必须放在服务器端表单中,也就是必须在<form runat=”server” id=”form 表单ID”></form> 标记之中。
(3 )HTML 服务器控件最终在Web 服务器处会被解释成普通HTML 控件标记发送到客户端浏览器。
asp.net 服务器控件是微软为了方便开发者开发而推出的一系列控件,它们都以类似<asp:* ID="btnOK" runat="server" …/> 的方式出现在Visual Studio 2005 的源视图里,* 代表了控件名,如<asp:Button ID="btnOK" runat="server" Text=" 提交" /> 就表示这是一个Button 控件。asp.net 服务器控件除了提供HTML 服务器控件所能提供的功能之外,还有很多功能更为复杂的控件。这些控件可以分为简单控件、容器控件、数据绑定控件、数据源控件和数据验证控及用户自己根据自己业务需要将一些控件组合在一起组成的用户控件等。
asp.net 控件的特点与HTML 服务器控件类似,也有如下特点:
(1)asp.net 服务器控件必须有一个在当前页面中唯一的ID 属性和runat=”server” 属性;
(2)asp.net 服务器控件必须放在服务器端表单中;
(3)asp.net 服务器控件最终会被解释成普通HTML 标记发送到客户端浏览器。

本文主要介绍以下控件:
Button 控件
TextBox 控件
Web 服务器控件的特殊客户端事件
FileUpload 控件
Literal 控件
Panel 控件
PlaceHolder 控件

Button 控件
Button 控件是asp.net 开发时最常见的控件之一,我们创建一个页面名为ServerControl.aspx ,下面就是这个页面的前台代码:

1. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ServerControl.aspx.cs" Inherits="ServerControl" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.  </head> 
9.  <body> 
10.     <form id="form1" runat="server"> 
11.     <div> 
12.     <table border="0" width="100%"> 
13.     <tr><td> 
14.         </td><td></td></tr> 
15.     <tr><td></td><td></td></tr> 
16.     <tr><td></td><td></td></tr> 
17.     <tr><td></td><td></td></tr> 
18.     <tr><td><asp:Button ID="btnOK" runat="server" Text="提交" /></td><td></td></tr> 
19.     </table> 
20.     </div> 
21.     </form> 
22. </body> 
23. </html>

这个页面在客户端一个只有一个提交按钮的页面,我们点击这个按钮的时候页面会刷新,它在客户端浏览器的HTML 代码如下:

1.   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
2.  
3.  <html xmlns="http://www.w3.org/1999/xhtml" > 
4.  <head><title> 
5.   无标题页 
6.  </title></head> 
7.  <body> 
8.      <form name="form1" method="post" action="ServerControl.aspx" id="form1"> 
9.  <div> 
10. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTQ2OTkzNDMyMWRkT/VDzJ0SWn3BqgG/UOUV4Cqu7NY=" /> 
11. </div> 
12. 
13.     <div> 
14.     <table border="0" width="100%"> 
15.     <tr><td> 
16.         </td><td></td></tr> 
17.     <tr><td></td><td></td></tr> 
18.     <tr><td></td><td></td></tr> 
19.     <tr><td></td><td></td></tr> 
20.     <tr><td><input type="submit" name="btnOK" value="提交" id="btnOK" /></td><td></td></tr> 
21.     </table> 
22.     </div> 
23.      
24. <div> 
25. 
26.  <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgKFss63DQLdkpmPAbagjAxymGXZUaR5sNMBZHmUjoKd" /> 
27. </div></form> 
28. </body> 
29. </html>

可见默认情况下,Button 控件被解释成<input type=”submit” …/> 形势的提交按钮,并且这个按钮的客户端id (即在HTML 代码中的id 属性)和我们在服务器端指定的id 是一致的。还有一点要说明的是,在设计时表单的代码是“<form id="form1" runat="server">” ,到了客户端变成了“<form name="form1" method="post" action="ServerControl.aspx" id="form1">” ,这也是幕后的工作,我们的表单发送到客户端时被设置成post 提交方式,接收表单数据的页面是当前页面(当前页面就是ServerControl.aspx )。
因为Button 控件默认生成HTML 的提交按钮,所以点击这个按钮自然就有了提交表单行为,并且默认是提交到当前页面处理。
Button 按钮常见属性有如下:

属性名

属性类型

属性说明

CausesValidation

bool 

指示在单击 Button 控件时是否执行验证

CommandArgument

string

该参数会传递到Command 事件

CssClass

string

该参数指示控件在客户端呈现的级联样式表(CSS) 类

Enabled

bool

指示是否启用 Web 服务器控件

OnClientClick

string

Button 控件的 Click 事件时所执行的客户端脚本

Text

string

在 Button 控件中显示的文本标题

ValidationGroup

string

Button 控件回发到服务器时要进行验证的控件组

  
Button 控件的常见事件

事件名

委托类型

事件说明

Click

EventHandler

单击Button 控件激发的事件

Command

CommandEventHandler

单击Button 控件激发的事件

  
今天要讲的是CommandArgument 、CssClass 、OnClientClick 属性和Click 及Command 事件。其它如CausesValidation 和ValidationGroup 会在验证控件部分再具体讲。
CssClass 这个属性非常有用,如果是单个按钮我们可以直接设置Button 的前景色、背景色及Style 属性,可是在大型网站中这么设置非常不方便,并且维护起来非常不方便。试想一下,在一个网站中有数百个甚至数千个Button 按钮,有一天客户想改变它们的风格,那么是多么枯燥的一件事情,CssClass 就是用来设置控件的css 属性的(这个属性很多控件都有),这样在外部css 样式文件中改变一下,整个网站的Button 控件显示风格全部变化了,非常方便。
OnClientClick 这个属性用于一些需要客户端交互的场合,比如点击这个按钮会从数据库删除一些数据,有可能客户无意中点了这个按钮,那么我们可以给用户一次确认的机会,一旦用户吃了秤砣铁了心要删除他只需要确认一下就可以,如果不小心碰上这个按钮还可以点击“ 否” 来取消。有经验的程序员在一些重要操作的时候都会给出这个提示,这个提示其实就是利用javascript 的confirm ()函数来实现。
Click 和Command 事件都是单击Button 按钮时发生的事件,可是处理它们的委托类型不同,激发Click 事件由 EventHandler 委托来处理,激发Command 事件后由CommandEventHandler 委托来处理,看看它们的声明:

1.  public delegate void EventHandler ( 
2.   Object sender, 
3.   EventArgs e 
4.  ) 
5.  
6.  public delegate void CommandEventHandler ( 
7.   Object sender, 
8.   CommandEventArgs e 
9.  )

看出区别来了吗?它们都有两个参数,第一个参数表示由哪个控件激发了事件,第二个参数表示发生事件时的一些事件数据。这两个委托第一个参数都是相同的,第二个参数不同,EventArgs 这个类不带有任何事件数据(这个委托很常见,不关心事件数据的事件都是用这个委托处理),而CommandEventArgs 可以附带事件数据,它有两个重要属性:CommandArgument 和CommandName 。CommandArgument 属性可以附带一些参数信息,CommandName 用于设置命名的名称。
下面对刚才的页面添加更多代码,前台代码如下:

1.    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ServerControl.aspx.cs" Inherits="ServerControl" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.      <style type="text/css"> 
9.      .zhoufoxcn 
10.     { 
11.     color:#0000C0; 
12.     background-color:Olive; 
13.     border-color:Red; 
14.     border-style:Dotted; 
15.     } 
16.     .redfoxcn 
17.     { 
18.     color:red; 
19.     background-color:Olive; 
20.     border-color:#0000C0; 
21.     border-style:Dotted; 
22.     } 
23.     </style> 
24. </head> 
25. <body> 
26.     <form id="form1" runat="server"> 
27.     <div> 
28.     <table border="0" width="100%"> 
29.     <tr><td> 
30.         </td><td></td></tr> 
31.     <tr><td></td><td></td></tr> 
32.     <tr><td></td><td></td></tr> 
33.     <tr><td> 
34.         </td><td></td></tr> 
35.     <tr><td><asp:Button ID="btnOK" runat="server" Text="Click" OnClientClick="javascript:return confirm('确认提交?')" OnClick="btnOK_Click" CssClass="zhoufoxcn" /></td><td> 
36.         <asp:Button ID="btnCommand" runat="server" 
37.             Text="Command" OnCommand="btnCommand_Command" CommandArgument="1" CssClass="redfoxcn" /></td></tr> 
38.     </table> 
39.     </div> 
40.     </form> 
41. </body> 
42. </html>

后台cs 代码如下:

1.  using System; 
2.  using System.Data; 
3.  using System.Configuration; 
4.  using System.Collections; 
5.  using System.Web; 
6.  using System.Web.Security; 
7.  using System.Web.UI; 
8.  using System.Web.UI.WebControls; 
9.  using System.Web.UI.WebControls.WebParts; 
10. using System.Web.UI.HtmlControls; 
11. 
12. public partial class ServerControl : System.Web.UI.Page 
13. { 
14.     protected void Page_Load(object sender, EventArgs e) 
15.     { 
16. 
17.     } 
18.     protected void btnOK_Click(object sender, EventArgs e) 
19.     { 
20.         Response.Write("发生了Click事件。"); 
21.     } 
22.     protected void btnCommand_Command(object sender, CommandEventArgs e) 
23.     { 
24.         Response.Write("发生了Command事件,事件的数据是:" + e.CommandArgument.ToString()); 
25.     } 
26. }

在前台代码中我们定义了css 样式,定义了两个css 类:zhoufoxcn 和redfoxcn 。ID 为“btnOK” 的Button 控件的CsssClass 属性为zhoufoxcn ,它的OnClientClick 属性为"javascript:return confirm(' 确认提交?')" ,用户在浏览器点击这个按钮的时候会弹出一个“ 确认提交?” 的询问对话框,用户点击“ 是” 提交当前表单,否则不会将表单提交到服务器进行处理,这个控件的OnClick 属性值为“btnOK_Click” ,“btnOK_Click” 是服务器上的一个方法,注意这个服务器方法一定要存在,并且满足EventHandler 委托参数类型要求,否则不会编译通过。另外ID 为“btnCommand” 的Button 控件的OnCommand 属性为“btnCommand_Command” ,这也是一个服务器端方法。给Button 控件添加OnClick 添加处理方法时双击就可以切换到cs 代码,服务器会自动添加相关代码,但是给OnCommand 添加相关处理方法时,不能这么做,只能通过在界面中找到该Button 控件,在属性栏中点击事件,双击Command 右边的空白处,如下图所示:

下面是浏览器中的HTML 代码:

1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
2.  
3.  <html xmlns="http://www.w3.org/1999/xhtml" > 
4.  <head><title> 
5.   无标题页 
6.  </title> 
7.      <style type="text/css"> 
8.      .zhoufoxcn 
9.      { 
10.     color:#0000C0; 
11.     background-color:Olive; 
12.     border-color:Red; 
13.     border-style:Dotted; 
14.     } 
15.     .redfoxcn 
16.     { 
17.     color:red; 
18.     background-color:Olive; 
19.     border-color:#0000C0; 
20.     border-style:Dotted; 
21.     } 
22.     </style> 
23. </head> 
24. <body> 
25.     <form name="form1" method="post" action="ServerControl.aspx" id="form1"> 
26. <div> 
27. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTQ3NjkyOTcyMmRkO5nkxzPqNMQvNwHngU2sXldPuhM=" /> 
28. </div> 
29. 
30.     <div> 
31.     <table border="0" width="100%"> 
32.     <tr><td> 
33.         </td><td></td></tr> 
34.     <tr><td></td><td></td></tr> 
35.     <tr><td></td><td></td></tr> 
36.     <tr><td> 
37.         </td><td></td></tr> 
38.     <tr><td><input type="submit" name="btnOK" value="Click" onclick="javascript:return confirm('确认提交?');" id="btnOK" class="zhoufoxcn" /></td><td> 
39.         <input type="submit" name="btnCommand" value="Command" id="btnCommand" class="redfoxcn" /></td></tr> 
40.     </table> 
41.     </div> 
42.      
43. <div> 
44. 
45.  <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwKfyNPeBgLdkpmPAQLmjabZCHH72VxzRufctQapudcEco8xXEb0" /> 
46. </div></form> 
47. </body> 
48. </html>

下面是运行情况:

点击“Click” 的情况:

点击“Command” 按钮后的运行情况:

需要注意的是:Click 事件和Command 事件不能同时使用,如果需要事件的数据,那么就用Command 事件,然后设置CommandEventArgs 属性来附带事件数据,如果不关心事件数据,那么直接用Click 属性就行了。

TextBox 控件
TextBox 控件用来提供一个输入框,这个输入框默认是输入单行文本的,但是我们可以设置它的TextMode 属性来控制输入框的形式。它可以是以下三个值:
TextMode="SingleLine" :用来输入单行文本
TextMode="Password" :用来输入密码
TextMode="MultiLine" :用来输入多行文本
下面对ServerControl.aspx 的前台再做一下改造,代码如下:

1.    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ServerControl.aspx.cs" Inherits="ServerControl" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.      <style type="text/css"> 
9.      .zhoufoxcn 
10.     { 
11.     color:#0000C0; 
12.     background-color:Olive; 
13.     border-color:Red; 
14.     border-style:Dotted; 
15.     } 
16.     .redfoxcn 
17.     { 
18.     color:red; 
19.     background-color:Olive; 
20.     border-color:#0000C0; 
21.     border-style:Dotted; 
22.     } 
23.     </style> 
24. </head> 
25. <body> 
26.     <form id="form1" runat="server"> 
27.     <div> 
28.     <table border="0" width="100%"> 
29.     <tr><td> 
30.         用户名</td><td> 
31.         <asp:TextBox ID="txtUserName" runat="server"></asp:TextBox></td></tr> 
32.     <tr><td> 
33.         密码</td><td> 
34.         <asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox></td></tr> 
35.     <tr><td> 
36.         简单介绍</td><td> 
37.         <asp:TextBox ID="TextBox3" runat="server" TextMode="MultiLine"></asp:TextBox></td></tr> 
38.     <tr><td> 
39.         </td><td></td></tr> 
40.     <tr><td><asp:Button ID="btnOK" runat="server" Text="Click" OnClientClick="javascript:return confirm('确认提交?')" OnClick="btnOK_Click" CssClass="zhoufoxcn" /></td><td> 
41.         <asp:Button ID="btnCommand" runat="server" 
42.             Text="Command" OnCommand="btnCommand_Command" CommandArgument="1" CssClass="redfoxcn" /></td></tr> 
43.     </table> 
44.     </div> 
45.     </form> 
46. </body> 
47. </html>

运行之后,我们在每个文本框都输入“zhoufoxcn” ,结果如下:

另外TextBox 控件还有一个属性:AutoPostBack 。这个属性默认是false ,即控件的值发生变化时不会自动自动发生提交,如果为true 就会自动向服务器提交(当控件失去焦点的时候向服务器提交),并且它还有一个事件TextChanged 专门用来处理TextBox 中的文本变化的情况的。
再对上面的代码变化一下,设置ID 为“txtUserName” 的控件的AutoPostBack 属性为true ,如下:

1.  <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ServerControl.aspx.cs" Inherits="ServerControl" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.      <style type="text/css"> 
9.      .zhoufoxcn 
10.     { 
11.     color:#0000C0; 
12.     background-color:Olive; 
13.     border-color:Red; 
14.     border-style:Dotted; 
15.     } 
16.     .redfoxcn 
17.     { 
18.     color:red; 
19.     background-color:Olive; 
20.     border-color:#0000C0; 
21.     border-style:Dotted; 
22.     } 
23.     </style> 
24. </head> 
25. <body> 
26.     <form id="form1" runat="server"> 
27.     <div> 
28.     <table border="0" width="100%"> 
29.     <tr><td> 
30.         用户名</td><td> 
31.         <asp:TextBox ID="txtUserName" runat="server" AutoPostBack="True" OnTextChanged="txtUserName_TextChanged"></asp:TextBox></td></tr> 
32.     <tr><td> 
33.         密码</td><td> 
34.         <asp:TextBox ID="txtPassword" runat="server" TextMode="Password"></asp:TextBox></td></tr> 
35.     <tr><td> 
36.         简单介绍</td><td> 
37.         <asp:TextBox ID="txtIntroduce" runat="server" TextMode="MultiLine"></asp:TextBox></td></tr> 
38.     <tr><td> 
39.         </td><td></td></tr> 
40.     <tr><td><asp:Button ID="btnOK" runat="server" Text="Click" OnClientClick="javascript:return confirm('确认提交?')" OnClick="btnOK_Click" CssClass="zhoufoxcn" /></td><td> 
41.         <asp:Button ID="btnCommand" runat="server" 
42.             Text="Command" OnCommand="btnCommand_Command" CommandArgument="1" CssClass="redfoxcn" /></td></tr> 
43.     </table> 
44.     </div> 
45.     </form> 
46. </body> 
47. </html>

双击ID 为“txtUserName” 的这个控件,就会自动产生一个事件,在这个事件中编写处理代码,如下:

1.   using System; 
2.  using System.Data; 
3.  using System.Configuration; 
4.  using System.Collections; 
5.  using System.Web; 
6.  using System.Web.Security; 
7.  using System.Web.UI; 
8.  using System.Web.UI.WebControls; 
9.  using System.Web.UI.WebControls.WebParts; 
10. using System.Web.UI.HtmlControls; 
11. 
12. public partial class ServerControl : System.Web.UI.Page 
13. { 
14.     protected void Page_Load(object sender, EventArgs e) 
15.     { 
16. 
17.     } 
18.     protected void btnOK_Click(object sender, EventArgs e) 
19.     { 
20.         Response.Write("发生了Click事件。"); 
21.     } 
22.     protected void btnCommand_Command(object sender, CommandEventArgs e) 
23.     { 
24.         Response.Write("发生了Command事件,事件的数据是:" + e.CommandArgument.ToString()); 
25.     } 
26.     protected void txtUserName_TextChanged(object sender, EventArgs e) 
27.     { 
28.         Response.Write("当前输入的用户名是:" + txtUserName.Text); 
29.     } 
30. }

当我们在用户名文本框输入用户名,并将光标从用户名文本框移开时,会出现如下情况:

也就是当用户光标移开用户名输入框时,会自动提交表单并由它在服务器端定义的方法处理。这样可以及时将反馈显示给用户,不过缺点是需要将整个表单提交给服务器,然后整页面发送到客户端浏览器,降低了服务器的处理效率,也加大了网络数据传输。对一些小型站点可以这么做,如果是大型网站就需要采用Ajax 方法来处理了,这也是为什么Visual Studio 2005 中默认这个属性为false 的原因了。

Web 服务器控件的特殊客户端事件
我们知道Web 服务器控件最终会解释成普通HTML 控件到客户端浏览器,比如TextBox 这个Web 服务器控件最终在客户端浏览器呈现为文本输入框控件、密码输入框控件或者文本框控件,这个由TextBox 的TextMode 属性来决定。用Web 服务器控件有一个缺点就是很多时候我们没有办法获得它解释成客户端控件之后的客户端事件。
下面是文本输入框控件在客户端的事件(下图截取自Dreamweaver 8 编辑器):

我们可以看到文本框控件有很多客户端事件。再看看对应的TextBox 控件拥有的事件智能提示:

从上面的截图中可以看到TextBox 控件也拥有很多事件,但是这些事件不是客户端的,而是服务器端的。
我们先写一个HTML 文件,代码如下:

1.   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
2.  <html xmlns="http://www.w3.org/1999/xhtml"> 
3.  <head> 
4.  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 
5.  <title>HTML控件的客户端事件</title> 
6.  <script language="javascript"> 
7.  //下面的方法根据敲击键盘的ASCII码值来判断是否敲击了数字键 
8.  //数字键的ASCII码值介于48到57之间,分别对应数字0到9 
9.  //当方法返回true的时候敲入的字符才能显示 
10. function judgeNumber(code) 
11. { 
12.  //alert(code); 
13.  if(code>=48&<=57) 
14.  { 
15.   return true; 
16.  } 
17.  else 
18.  { 
19.   return false; 
20.  } 
21. } 
22. //英文字母A-Z的ASCII码值65-90,a-z的ASCII码值是97-122 
23. //当方法返回true的时候敲入的字符才能显示 
24. function judgeChar(code) 
25. { 
26.  //alert(code); 
27.  if((code>=65&<=90)||(code>=97&<=122)) 
28.  { 
29.   return true; 
30.  } 
31.  else 
32.  { 
33.   return false; 
34.  } 
35. } 
36. </script> 
37. </head> 
38. 
39. <body> 
40. <form> 
41. 数字:<input type="text" name="userName" onkeypress="return judgeNumber(event.keyCode);" /><br/> 
42. 字母:<input type="text" name="password" onkeypress="return judgeChar(event.keyCode);" /> 
43. </form> 
44. </body> 
45. </html>

这个页面的运行效果如下:

上面的页面效果是:第一个文本框只能输入数字,第二个文本框只能大小写字母。我们能知道TextBox 如果TextMode 是SingleLine 的话(这个是默认值,无需手动添加),最后在客户端浏览器也是普通文本框,那么我们可不可以给TextBox 控件加上上面的效果呢?答案是可以的。
在Visual Studio 2005 新建一个名为“TextBoxClient” 页面窗体,在源视图中粘贴如下代码:

1.    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="TextBoxClient.aspx.cs" Inherits="TextBoxClient" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.      <script language="javascript" type="text/javascript"> 
9.  //下面的方法根据敲击键盘的ASCII码值来判断是否敲击了数字键 
10. //数字键的ASCII码值介于48到57之间,分别对应数字0到9 
11. //当方法返回true的时候敲入的字符才能显示 
12. function judgeNumber(code) 
13. { 
14.  //alert(code); 
15.  if(code>=48&<=57) 
16.  { 
17.   return true; 
18.  } 
19.  else 
20.  { 
21.   return false; 
22.  } 
23. } 
24. //英文字母A-Z的ASCII码值65-90,a-z的ASCII码值是97-122 
25. //当方法返回true的时候敲入的字符才能显示 
26. function judgeChar(code) 
27. { 
28.  //alert(code); 
29.  if((code>=65&<=90)||(code>=97&<=122)) 
30.  { 
31.   return true; 
32.  } 
33.  else 
34.  { 
35.   return false; 
36.  } 
37. } 
38. </script> 
39. </head> 
40. <body> 
41.     <form id="form1" runat="server"> 
42.     <div> 
43.         数字:<asp:TextBox ID="TextBox1" runat="server" onkeypress="return judgeNumber(event.keyCode);"></asp:TextBox><br /> 
44.         字母:<asp:TextBox ID="TextBox2" runat="server" onkeypress="return judgeChar(event.keyCode);"></asp:TextBox></div> 
45.     </form> 
46. </body> 
47. </html>

上面的程序在客户端的最终效果和用普通HTML 控件的效果一样,只不过在Visual Studio 2005 源视图会得到如图所示的提示:

好在只是绿色波浪线,表示警告,所以还是能通过编译并且能运行的,如果是红色波浪线表示是错误,就没有办法运行了。对于Visual Studio 2005 来说,它并不认识那些javascript 客户端事件,尽管警告,不过它还是照原样输出了,到了客户端就成了普通HTML 控件,浏览器能识别这些,所以能正确运行。

FileUpload 控件
FileUpload 控件是一个很重要的控件,它被Web 服务器最终解释为形如“<input type=”file”…/>” 这样的普通HTML 控件。
它有如下常见属性:

属性名

数据类型

说明

FileBytes

byte[]

上传的文件内容的字节数组表示形式

FileContent

Stream

上传文件的数据流

FileName

string

上传文件在客户端的名字

HasFile

bool 

指示是否上传了文件

PostedFile

HttpPostedFile

获取文件基础的HttpPostedFile 对象

  
这个HttpPostedFile 对象能帮我们做很多工作,它也有一些有用的常见属性:

属性名

数据类型

说明

ContentLength

int

上传的文件内容的字节长度

ContentType

string

上传文件的MIME 内容类型

FileName

string

上传文件的在客户端的名字

InputStream

Stream

指向上传文件的Stream 对象

FileUpload 控件还有一个void SaveAs (string filename) 的方法,这个方法用于将上传的文件保存到服务器上。一般来说,使用FileUpload 控件上传文件一般有如下几个步骤:
(1 )利用HasFile 属性判断是否上传了文件。
(2 )在服务器上指定一个物理路径,并检查这个物理路径是否存在,如果不存在则先创建。
(3 )指定上传文件在服务器上的上传路径,利用SaveAs() 保存上传的文件。这一步还可以做一些其它检查工作,比如检查上传的文件格式是否符合要求或文件内容大小是否符合要求。
(4 )将相对路径或者URL 地址保存起来,以便客户访问或者下载。
这里要着重强调的是:我们保存上传的时候保存文件用的是物理路径,但是要保存的、日后客户端能访问得到的却是相对路径或者URL 地址。
下面是一个简单的例子,这个页面叫Upload.aspx ,它的源视图代码如下:

1.  <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Upload.aspx.cs" Inherits="Upload" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>文件上传的例子</title> 
8.  </head> 
9.  <body> 
10.     <form id="form1" runat="server"> 
11.     <div> 
12.         <asp:FileUpload ID="fileUpload" runat="server" /> 
13.         <asp:Button ID="btnUpload" runat="server" OnClick="btnUpload_Click" Text="上传" /> 
14.         <asp:Literal ID="literal" runat="server"></asp:Literal></div> 
15.     </form> 
16. </body> 
17. </html>

后台cs 代码如下:

1.  using System; 
2.  using System.Data; 
3.  using System.Configuration; 
4.  using System.Collections; 
5.  using System.Web; 
6.  using System.Web.Security; 
7.  using System.Web.UI; 
8.  using System.Web.UI.WebControls; 
9.  using System.Web.UI.WebControls.WebParts; 
10. using System.Web.UI.HtmlControls; 
11. 
12. public partial class Upload : System.Web.UI.Page 
13. { 
14.     protected void Page_Load(object sender, EventArgs e) 
15.     { 
16. 
17.     } 
18.     protected void btnUpload_Click(object sender, EventArgs e) 
19.     { 
20.         //判断是否上传了文件 
21.         if (fileUpload.HasFile) 
22.         { 
23.             //指定上传文件在服务器上的保存路径 
24.             string savePath = Server.MapPath("~/upload/"); 
25.             //检查服务器上是否存在这个物理路径,如果不存在则创建 
26.             if (!System.IO.Directory.Exists(savePath)) 
27.             { 
28.                 //需要注意的是,需要对这个物理路径有足够的权限,否则会报错 
29.                 //另外,这个路径应该是在网站之下,而将网站部署在C盘却把上传文件保存在D盘 
30.                 System.IO.Directory.CreateDirectory(savePath); 
31.             } 
32.             savePath = savePath + "\\" + fileUpload.FileName; 
33.             fileUpload.SaveAs(savePath);//保存文件 
34.             //不过需要注意的是,在客户端访问却需要指定的是URL地址,而不是在服务器上的物理地址 
35.             literal.Text = string.Format("<a href='upload/{0}'>upload/{0}</a>", fileUpload.FileName); 
36.         } 
37.     } 
38. }

 

以下是程序运行结果:


上传文件之后的效果:

因为我上传了一个proc.txt 的文件,所以最后的URL 地址是:upload/proc.txt ,点击这个超级链接能打开刚刚上传的文件查看其内容,如下图:

注意:对于有些文件,如rar 格式的,点击之后则会出现下载提示而不是直接在浏览器打开。

带图片预览功能的FileUpload 控件
通过上面的讲述,我们知道一些web 服务器控件在vs2005 下没有javascript 客户端事件的提示,不过只要我们确信这个事件对应的HTML 控件确实有,我们可以自行添加的,下面我们就来做一个让FileUpload 控件带有图片预览功能的例子。
因为这里不涉及到上传后如何保存,只是仅仅在用户选择了要上传的文件时或者用户将鼠标移动到上传控件上时,如果上传的文件是图片文件,我们就显示这个图片的预览效果5 分钟,然后消失。以下是程序代码(前台代码,保存代码和上面的例子一样,所以没有写后台cs 代码):

1.  <%@ Page Language="C#" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <script runat="server"> 
6.  
7.  </script> 
8.  
9.  <html xmlns="http://www.w3.org/1999/xhtml" > 
10. <head runat="server"> 
11.     <title>上传图片预览实例</title> 
12.     <script type="text/javascript" language="javascript"> 
13. //如果用户选择了图片,则显示图片的预览效果 
14. function previewImage() 
15. { 
16.   var x = document.getElementById("file"); 
17.   if(!x || !x.value)//如果没有选择上传文件 
18.   { 
19.      return; 
20.    } 
21.     var patn = /\.jpg$|\.jpeg$|\.gif$/i; 
22.     if(patn.test(x.value))//如果上传文件的后缀是.jpg或.jpeg或.gif 
23.     {     
24.         var y = document.getElementById("img"); 
25.         if(y) 
26.         {       
27.             y.src = 'file://localhost/' + x.value; 
28.             y.style.display="block";  
29.         } 
30.         else 
31.         { 
32.             var img=document.createElement('img');       
33.             img.setAttribute('src','file://localhost/'+x.value);       
34.             img.setAttribute('width','120');       
35.             img.setAttribute('height','90');       
36.             img.setAttribute('id','img');       
37.             document.getElementById('form1').appendChild(img);       
38.         } 
39.         setTimeout("hidden()",5000); //5秒之后执行隐藏图片的javascript方法 
40.     } 
41.     else 
42.     {     
43.         alert("您选择的似乎不是图像文件。");   
44.     } 
45. } 
46. //隐藏照片 
47. function hidden() 
48. { 
49.     var y = document.getElementById("img"); 
50.     if(y) 
51.     { 
52.         document.getElementById('img').style.display="none"; 
53.     } 
54. } 
55. </script> 
56. </head> 
57. <body> 
58.     <form id="form1" runat="server"> 
59.     <div> 
60.          <asp:FileUpload ID="file" runat="server" onchange="previewImage()" onmouseover="previewImage()" /> 
61.         <asp:Button ID="btnUpload" runat="server" Text="上传" /></div> 
62.     </form> 
63. </body> 
64. </html>

说明一下,在这个页面里form 表单的id 是form1, 上传控件的id 是file ,所以在客户端用到了document.getElementById() 这个方法来获取相关的控件的属性值,并且通过javascript 脚本动态添加了一个<img id=”img”> 的控件,然后我们操纵它的src 属性来决定显示哪张图片,利用它的style.display 属性来决定是否显示。
以下预览时的效果:

预览5 秒钟之后,不再带有预览功能的效果:

注意:如果我们要上传文件,需要给表单增加enctype="multipart/form-data" 属性,如果我们使用了FileUpload 控件时,生成HTML 代码时表单会自动加上这个属性。

Literal 控件
Literal 控件是一个类似于Label 控件的控件,都是用来呈现文字的。前面我说过,虽然通过Response.Write() 方法可以直接输出文字,但是这样输出的文字有可能在<html></html> 标记之外,破坏了网页的结构,使之不再符合XHTML 标准。
对于静态文字,我们可以直接在HTML 代码中书写即可,而没有必要使用Literal 控件或 Label 控件。但是在某些情况下我们却希望在某个位置设置一些文字,那么我们就可以先在期望输出文字的地方放置一个Literal 控件,将来在程序代码中根据程序逻辑动态设置Literal 控件的Text 属性来控制要输出的文字。
尽管在某种程度上,Literal 控件用法与 Label 控件用法类似,但是不同的是 Literal 控件不能用于将css 样式应用于显示的文本。
另外Literal 控件还有一个Mode 属性,它用来控制如何呈现Literal 控件中的内容。这个属性是一个枚举,有三个枚举值:
PassThrough :直接呈现Literal 控件中的内容。
Encode :控件的内容转换为 HTML 编码的字符串。
Transform :从控件的内容中移除不受支持的标记语言元素。如果Literal 控件在支持 HTML 或 XHTML 的浏览器上呈现,则不会修改该控件的内容。
举例说明,假如Literal 的Text 属性为“<abc>http://blog.csdn.net/zhoufoxcn</abc>” ,即如下代码:

<table border="1" width="600" cellpadding="1" cellspacing="1"> 
2.          <tr><td> 
3.               
4.                  Mode</td><td> 
5.            效果</td></tr> 
6.          <tr><td> 
7.              PassThrough</td><td> 
8.              <asp:Literal ID="Literal1" runat="server" Mode="PassThrough" Text="<abc>http://blog.csdn.net/zhoufoxcn</abc>"></asp:Literal></td></tr> 
9.          <tr><td> 
10.             Encode</td><td> 
11.             <asp:Literal ID="Literal2" runat="server" Mode="Encode" Text="<abc>http://blog.csdn.net/zhoufoxcn</abc>"></asp:Literal></td></tr> 
12.         <tr><td> 
13.             Transform</td><td> 
14.             <asp:Literal ID="Literal3" runat="server" Text="<abc>http://blog.csdn.net/zhoufoxcn</abc>"></asp:Literal></td></tr> 
15.         </table>

在浏览器的效果如下:

它们生成相关HTML 代码如下:

1.    <table border="1" width="600" cellpadding="1" cellspacing="1"> 
2.          <tr><td> 
3.               
4.                  Mode</td><td> 
5.            效果</td></tr> 
6.          <tr><td> 
7.              PassThrough</td><td> 
8.              <abc>http://blog.csdn.net/zhoufoxcn</abc></td></tr> 
9.          <tr><td> 
10.             Encode</td><td> 
11.             <abc>http://blog.csdn.net/zhoufoxcn</abc></td></tr> 
12.         <tr><td> 
13.             Transform</td><td> 
14.             <abc>http://blog.csdn.net/zhoufoxcn</abc></td></tr> 
15.         </table>

在浏览器中查看的时候,PassThrough 和Transform 模式的效果是一样的,但是如果用智能设备查看的时候,PassThrough 在客户端的代码仍然是<abc>http://blog.csdn.net/zhoufoxcn</abc> ,而Transform 模式在客户端的代码是http://blog.csdn.net/zhoufoxcn ,要注意这个差别,Literal 控件Mode 属性默认是Transform 模式。

Panel 控件
Panel 控件是一个容器控件,用来存储一组容器控件,它常用来存放一组业务逻辑上相似的控件组。下面看一个例子,这个例子里会根据用户选择的性别动态决定对象配偶的名字,如果是男性则让填写妻子的名字,如果是女性则让填写丈夫的名字,源视图代码如下:

1.  <%@ Page Language="C#" AutoEventWireup="true" CodeFile="PanelDemo.aspx.cs" Inherits="PanelDemo" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head runat="server"> 
7.      <title>无标题页</title> 
8.  </head> 
9.  <body> 
10.     <form id="form1" runat="server"> 
11.     <div> 
12.         性别:<asp:RadioButton ID="rbMale" runat="server" AutoPostBack="True" Checked="True" OnCheckedChanged="RadioButton_CheckedChanged" Text="男" GroupName="sex" /> 
13.         <asp:RadioButton ID="rbFemale" runat="server" Text="女" AutoPostBack="True" GroupName="sex" OnCheckedChanged="RadioButton_CheckedChanged" /><br /> 
14.         <asp:Panel ID="pMale" runat="server" Height="50px" Width="125px"> 
15.         妻子姓名:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> 
16.         </asp:Panel> 
17.         </div> 
18.         <asp:Panel ID="pFemale" runat="server" Height="50px" Width="125px" Visible="False"> 
19.         丈夫姓名:<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> 
20.         </asp:Panel> 
21.     </form> 
22. </body> 
23. </html>

在这里我们用了两个RadioButton 控件,并且设置了它们的GroupName 属性都为“sex” ,表示这两个RadioButton 属于一个分组,它们之中只能有一个处于选中状态,另外我们还设置了这两个RadioButton 控件的AutoPostBack 属性都为“true” ,表示当它们的选择状态发生变化的时候,将会自动提交到服务器进行处理,并且对于它们在服务器端的处理都都使用了同一个方法RadioButton_CheckedChanged ,后台代码如下:

1.    using System; 
2.  using System.Data; 
3.  using System.Configuration; 
4.  using System.Collections; 
5.  using System.Web; 
6.  using System.Web.Security; 
7.  using System.Web.UI; 
8.  using System.Web.UI.WebControls; 
9.  using System.Web.UI.WebControls.WebParts; 
10. using System.Web.UI.HtmlControls; 
11. 
12. public partial class PanelDemo : System.Web.UI.Page 
13. { 
14.     protected void Page_Load(object sender, EventArgs e) 
15.     { 
16. 
17.     } 
18.     protected void RadioButton_CheckedChanged(object sender, EventArgs e) 
19.     { 
20.         //如果选择的性别是“男”,则让填写妻子的姓名 
21.         if (rbMale.Checked) 
22.         { 
23.             pMale.Visible = true; 
24.             pFemale.Visible = false; 
25.         } 
26.         else//否则让填写丈夫的姓名 
27.         { 
28.             pMale.Visible = false; 
29.             pFemale.Visible = true; 
30.         } 
31.     } 
32. }

程序的运行效果如下:

选择“ 女” 之后的变化:
 
我们可以查看Panel 控件生成的代码:

1.    <div> 
2.          性别:<input id="rbMale" type="radio" name="sex" value="rbMale" checked="checked" /><label for="rbMale">男</label> 
3.          <input id="rbFemale" type="radio" name="sex" value="rbFemale" onclick="javascript:setTimeout('__doPostBack(\'rbFemale\',\'\')', 0)" /><label for="rbFemale">女</label><br /> 
4.          <div id="pMale" style="height:50px;width:125px;"> 
5.  
6.          妻子姓名:<input name="TextBox1" type="text" id="TextBox1" /> 
7.           
8.  </div> 
9.          </div> 
10.          
11.      
12. <div>

上面的代码是当选择“ 男” 的时候生成的代码,可见对于Panel 控件在客户端的代码为一个<div> 标记。

PlaceHolder 控件
PlaceHolder 控件控件的作用和Panel 控件的作用非常类似,也是用作容器控件,不过控件本身在客户端不产生任何可见HTML 标记。
PlaceHolder 控件有一个Controls 属性,这个属性表示这个容器控件容纳的控件的集合,Controls 属性是ControlCollection 类的一个实例,这个类用Add() 方法向集合中增加控件,用Remove() 删除控件,还有一个Count 属性表示这个集合中总共有多少个控件。

下面是一个PlaceHolder 控件用法的例子,为了简单起见,我没有采用代码和页面分离的模式,代码如下:

1.    <%@ Page Language="C#" %> 
2.  
3.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
4.  
5.  <script runat="server"> 
6.  
7.      protected void Page_Load(object sender, EventArgs e) 
8.      { 
9.          Button btn = new Button(); 
10.         btn.Text = "动态添加的控件"; 
11.         btn.Click += new EventHandler(btn_Click);//给动态添加的Button的单击事件增加服务器端方法 
12.         PlaceHolder1.Controls.Add(btn); 
13.     } 
14. 
15.     public void btn_Click(object sender, EventArgs e) 
16.     { 
17.         Literal l = new Literal(); 
18.         l.Text = "PlaceHolder1控件总共容纳了" + PlaceHolder1.Controls.Count + "个控件"; 
19.         PlaceHolder1.Controls.Add(l); 
20.     } 
21. </script> 
22. 
23. <html xmlns="http://www.w3.org/1999/xhtml" > 
24. <head runat="server"> 
25.     <title>无标题页</title> 
26. </head> 
27. <body> 
28.     <form id="form1" runat="server"> 
29.     <div> 
30.         <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder> 
31.      
32.     </div> 
33.     </form> 
34. </body> 
35. </html>

程序的运行结果:

点击按钮之后的效果:

在没有点击按钮之前客户端浏览器得到的HTML 代码如下:

1.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
2.  
3.  
4.  
5.  <html xmlns="http://www.w3.org/1999/xhtml" > 
6.  <head><title> 
7.   无标题页 
8.  </title></head> 
9.  <body> 
10.     <form name="form1" method="post" action="PlaceHolderDemo.aspx" id="form1"> 
11. <div> 
12. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM2NTY5NjE1NWRkDxPVOfW9ygVx0MnTmn1nNCXGfWY=" /> 
13. </div> 
14. 
15.     <div> 
16.         <input type="submit" name="ctl02" value="动态添加的控件" />PlaceHolder1控件总共容纳了1个控件 
17.      
18.     </div> 
19.      
20. <div> 
21. 
22.  <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgLhoKDXAwKfwImNCxlfxrs8MWJR7ujk/rFzZ1UfCrph" /> 
23. </div></form> 
24. </body> 
25. </html>

小结 :Panel 和PlaceHolder 作为控件的容器,在很多地方是相似的,不同的是PlaceHolder 不会在客户端产生任何可见的输出,而Panel 还可以设置背景图片等。
Label 和Literal 控件常用来显示文字(也可以成为文本的容器哦),在很多地方是相似的,不过不能设置Literal 的客户端css 样式,并且Literal 对显示的文本的控制能力更灵活一些,利用Mode 属性可以方便地显示HTML 代码。

 

 

 

Asp.net 夜话系列文章:

·        Asp.net夜话之一: asp.net介绍

·        Asp.net夜话之二: asp.net内置对象

·        asp.net夜话之三:表单和控件

·        Asp.net夜话之四: Visual Studio 2005中容易被忽略的技巧

·        asp.net夜话之五: Page类和回调技术

·        asp.net夜话之六: asp.net基本控件

·        asp.net夜话之七: ADO.NET介绍

·        asp.net夜话之八:数据绑定控件

·        asp.net夜话之九:验证控件

·        asp.net夜话之十:复合控件和母板页

·        asp.net夜话之十一: web.config详解