第4章 C#程序设计基础
C#是Visual Studio提供的、主要用于ASP.NET程序设计的编程语言,它采用事件驱动机制来组织程序流程。虽然C#采用了完全面向对象的程序设计方法,但在编写程序代码时,对于具体的代码块仍涉及流程控制问题。也就是说面向对象的程序设计方法包容了面向过程的结构化程序设计方法。
4.1 C#程序设计方法
结构化程序设计方法把程序的结构规定为顺序、选择和循环3种基本结构。尽量避免语句间的跳转,设计时要求自顶向下、逐步求精和模块化程序设计等设计原则。其目的是为了解决团队开发大型软件时,如何实现高效率、高可靠性的问题。
面向对象的程序设计方法,将所有问题均看作一个“对象”,程序通过对象的属性、事件和方法来实现所需功能。在面向对象的程序设计方法中将相似的对象看作一个“类”,而对象则是类的实例化结果。
4.1.1 事件驱动机制
所谓“事件”,是指能被程序感知到的用户或系统发起的操作。如用户单击了鼠标、输入了文字、选择了选项,以及系统将窗体装入内存并初始化等。Visual Studio中包含了大量已定义的隶属于各种控件的事件,如Click()、Load()和TextChange()等。在代码窗口中,设计人员可以编写响应事件的代码段来实现程序的具体功能,这就是可视化程序设计方法的事件驱动机制。当然,除了系统预定义的各种事件外,还可以通过委托创建具有特定功能的自定义事件来满足程序设计的需要。
【演练4-1】设计一个简单的算术计算器程序,通过设计理解常用Web服务器端控件的使用方法和顺序结构程序设计的特点。
(1)设计要求
程序启动后显示如图4-1所示的Web页面,浏览器标题文字为“简单算术计算器”。用户可在第1和第2个文本框中分别输入两个数字,再单击“+”“-”“×”“÷”中的一个,在第3个文本框中将显示按用户选择的方式得出的计算结果。
(2)设计Web页面
为了定位各控件的布局,首先向Web窗体中添加一个5列4行的HTML表格。分别选中第1、3、4、5列中所有单元格并右击,在弹出的快捷菜单中选择“修改”→“合并单元格”命令。当然,HTML表格行列数的调整也可以通过在源视图中直接修改HTML代码来实现。
将光标分别定位到第1、3、5列,双击工具箱“标准”选项中的TextBox图标,向Web页面中添加3个文本框控件TextBox1~TextBox3。
将光标分别定位到第2列的4个单元格中,双击工具箱“标准”选项中的Button图标,向页面中添加4个按钮控件Button1~Button4。将光标定位到第4列直接在单元格中输入一个等号。页面设计结果如图4-2所示。
图4-1 程序运行结果
图4-2 设计Web页面
(3)设置对象属性
分别选择页面中的各控件对象,在“属性”窗口中按表4-1所示设置它们的初始属性。
表4-1 各控件对象的属性设置
为美化程序界面,还可以通过各控件的Font属性集对显示字体进行必要的设置。
(4)编写事件代码
1)双击Web窗体的空白处,切换到代码视图编写页面载入时执行的事件代码。
2)“+”按钮被单击时执行的事件代码如下。
3)“-”按钮被单击时执行的事件代码如下。
4)“×”按钮被单击时执行的事件代码如下。
5)“÷”按钮被单击时执行的事件代码如下。
(5)运行并检测正确性
程序运行后分别在前两个文本框中输入一个数据,单击某个运算按钮进行计算,并检测计算结果的正确性。
需要注意以下两点。
1)程序由5个事件处理程序组成(1个系统事件,4个用户事件),启动时触发系统事件Page_Load,自动执行事件代码,执行完毕后程序运行暂停,等待下一个事件的触发。用户单击某个运算按钮时触发用户单击事件,程序再执行对应的事件处理代码给出响应。如果系统或用户不再触发任何事件,则程序会一直等待下去,直到浏览器关闭程序运行结束。
2)在事件代码块中声明的变量为“局部变量”,当事件处理结束后变量将被自动释放,故本例需要在每个事件处理程序段中都进行变量声明。若希望声明的变量在所有事件中均可用(事件处理结束后变量中的数据仍可保留),则应将其声明在所有事件处理程序之外,一般可在Web窗体类声明语句下方书写声明语句,这样的变量称为窗体级变量,只有当页面关闭时变量才会被释放。举例如下。
4.1.2 选择结构程序设计
所谓选择结构,是指程序可以根据一定的条件有选择地执行某一程序段。也就是说,对不同的问题采用不同的处理方法。C#提供了多种形式的条件语句来实现选择结构。
1.if…else语句
if语句是程序设计中基本的选择语句,if语句的语法格式如下。
if(条件表达式)
{语句序列1;}
else
{语句序列2;}
有以下3点需要说明。
1)条件表达式可以是关系表达式、逻辑表达式(布尔表达式)或逻辑常量值真(true)与假(false),当条件表达式的值为真时,程序执行语句序列1,否则执行语句序列2。
2)语句序列1和语句序列2可以是单语句,也可以是语句块。如果语句序列中为单语句,则大括号可以省略。
3)else子句为可选部分,可根据实际情况决定是否需要该部分。
根据条件表达式的值进行判断,当该值为真(true)时执行if后的语句序列;当该值为假时,执行else后的语句序列。该结构一般用于两种分支的选择。下面结合实例来介绍if…else语句的使用方法。
【演练4-2】求函数值,输入x,计算y的值,计算方法如下。
程序运行后,在第1个文本框中输入了x值,单击“计算”按钮,第2个文本框中将显示相应的y值,同时“计算”按钮变为“清除”按钮,单击“清除”按钮可清除上次的计算结果,按钮恢复成“计算”。若用户没有输入数据或输入了非法数据值后单击“计算”按钮,程序将显示出错提示信息。程序运行结果如图4-3所示。
图4-3 程序运行结果
程序设计步骤如下。
(1)问题分析
该问题是数学中的一个分段函数,它表示当x≥0时,用公式y=4x来计算y的值,当x<0时,用公式y=15-2x来计算y的值。在选择条件时,既可以选择x≥0作为条件,也可以选择x<0作为条件。这里选择x≥0作为选择条件。当x≥0为真时,执行y=4x;为假时,执行y=15-2x。
程序中可设计一个专门用于根据x值计算y值的自定义方法。单击“计算”按钮时,首先对用户的输入进行验证,若通过验证则调用计算方法得出y值,并将“计算”改为“清除”,否则弹出信息框显示出错提示。
(2)设计Web页面
新建一个ASP.NET空网站,向网站中添加一个Web窗体页Default.aspx。向Default.aspx中添加一个用于布局的、1行3列的HTML表格,直接向表格中输入说明文字并添加一个图片框控件Image1(用于显示函数表达式图片),两个文本框控件TextBox1和TextBox2,一个按钮控件Button1。
设置TextBox1的ID属性为txtX,TextBox2的ID属性为txtY,Button1的ID属性为bt- nOK,Text属性为“计算”。
在网站文件夹下新建一个名为images的子文件夹,将事先准备好的函数表达式图片复制到该文件夹中。
(3)编写事件代码
1)窗体载入时执行的事件代码如下。
2)命令按钮被单击时执行的事件代码如下。
3)用于计算函数值的Cal方法的代码如下。
说明:通过自定义方法可以将程序的核心功能从事件处理程序中分离出来。事件处理程序仅用于设置控件属性、接收用户的输入和验证用户输入等方面。这种分层设计的方式可以使程序结构更加清晰,可读性更高,也有利于代码段的复用。
2.if…else if语句
使用if…else if语句可以进行多条件判断,适合用于对3种或3种以上的情况进行判断的选择结构,实际上if…else if语句是一种if语句嵌套结构。if…else if语句的语法结构如下。
【演练4-3】某学校规定,校内职务津贴按教师技术职称发放。发放标准如下。
教授,1200元;副教授,800元;讲师,500元;助教,300元;要求设计程序能根据用户输入的职称,计算出应得的职务津贴。
程序设计步骤如下。
(1)问题分析
这是一个典型的多条件选择问题,程序在用户输入了数据后,首先判断输入是否有效(输入的是“教授”“副教授”“讲师”和“助教”四者之一),若输入有误则显示提示信息并返回到初始状态。若有效则按“教授”→“副教授”→“讲师”的顺序进行判断,并显示对应的津贴数额。若所有条件均不成立,则用户输入的职称一定是“助教”,故无须再进行判断。
(2)设计Web界面
向页面中添加一个文本框控件TextBox1,用于接收用户输入的职称数据。添加一个标签控件Label1,用于输出相应的职务津贴值。添加一个按钮控件Button1,用于触发单击事件执行计算程序。
(3)编写事件代码
命令按钮被单击时执行的事件代码如下。
说明:本例使用了if…else语句,并在其中嵌套了一个if…else if语句,在阅读程序时应首先认真理解程序流程,分清程序的层次结构。
3.switch语句
如果在多重分支的情况下,虽然可以使用if语句实现,但层次较多,结构比较复杂,而使用专门的多重分支选择语句switch语句,则可以使多重分支选择结构的设计更加方便。switch语句的语法格式如下。
其中,“控制表达式”所允许的数据类型为整数类型(sbyte、byte、short、ushort、uint、long、ulong)、字符类型(char)、字符串类型(string)或者枚举类型。
各个case语句后的常量表达式的数据类型与控制表达式的类型相同,或能够隐式转换为控制表达式的类型。
switch语句基于控制表达式的值选择要执行的语句分支。switch语句按以下顺序执行。
1)控制表达式求值。
2)如果case标签后的常量表达式的值等于控制表达式的值,则执行其后的内嵌语句。
3)如果没有常量表达式等于控制表达式的值,则执行default标签后的内嵌语句。
4)如果控制表达式的值不满足case标签,并且没有default标签,则跳出switch语句执行后续语句。
需要注意的是,如果case标签后含有语句序列,则语句序列最后必须使用break语句,以便跳出switch结构,因为缺少break语句将会产生编译错误。
将上例用switch结构改写后的代码如下。
在switch语句中,多个case标记可以使用同一处理语句序列。例如,将百分制学生成绩转换为十分制后再评定优良等级,设9分以上为“优”,7分以上为“良”,6分为“及格”,6分以下为“不及格”。要求用文本框TextBox1接收用户输入的百分值,使用标签La-bel1输出等级值(优、良、及格、不及格)。
实现代码如下。
4.1.3 循环结构程序设计
循环是在指定的条件下重复执行某些语句的运行方式。例如,计算学生总分时没有必要对每个学生都编写一个计算公式,可以在循环结构中使用不同的数据来简化程序的设计。
C#中提供了4种循环语句:for循环、while循环、do…while循环和foreach循环。其中,for和while是最常用的循环语句。
1.for循环
for循环常常用于已知循环次数的情况(也称为“定次循环”),使用该循环时,测试是否满足某个条件,如果满足条件,则进入下一次循环,否则,退出该循环。for循环语句的语法格式如下。
for(表达式1;表达式2;表达式3)
{
循环语句序列(循环体);
}
其中各部分的说明如下。
表达式1:用于设置循环变量的初始值,该表达式仅初次进入循环时执行一次。
表达式2:为条件判断表达式,即每次执行循环语句序列前,判断该表达式是否成立。如果成立,则执行循环语句序列(进入循环体);否则循环结束,执行循环语句的后续语句。
表达式3:用于改变循环变量值,一般通过递增或递减来实现。循环语句序列是每次循环重复执行的语句(性质相同的操作),当语句序列中仅含有一条语句时,大括号可以省略。
例如,下列代码表示当用户分别在TextBox1和TextBox2中输入一个整数范围后,单击命令按钮Button1,将在Label1和Label2中分别显示范围内所有偶数的和及所有奇数的和。
说明:for循环的循环变量i的值从用户输入的范围起始值(输入在TextBox1中的值)开始,到范围结束值(TextBox2的值)结束,每次循环i值加1。这使得程序能对范围内的所有数据实现遍历。
2.while循环
在实际应用中经常会遇到一些不定次循环的情况。例如,统计全班学生的成绩时,不同班级的学生人数可能是不同的,这就意味着循环的次数在设计程序时无法确定,能确定的只是某条件被满足(例如,后面不再有任何学生了)。此时,使用while循环最为合适。
while循环非常适合这种情况。循环时在循环的顶部判断某个条件是否满足,当循环的
条件判断为真时(满足条件),进入循环,否则退出循环。while循环语句的格式如下。
while(条件表达式)
{
循环语句序列;
}
条件表达式是每次进入循环前需要进行判断的条件,当条件表达式的值为true时,执行循环,否则退出循环。
在使用while循环时应注意以下几个问题。
1)条件表达式为关系表达式或逻辑表达式,其运算结果为true(真)或false(假)。在条件表达式中必须包含控制循环的变量,即循环变量。
2)作为循环体的语句序列可以是多条语句,也可以是一条语句。如果是一条语句,大括号可以省略。如果省略了大括号,则循环语句后碰到的第一个分号即为循环的结尾。
3)循环语句序列中至少应包含改变循环条件的语句(即条件表达式的值有可能为false),以避免陷入永远无法结束的“死循环”。
例如,要求程序产生一系列的随机整数,当产生的随机整数正好为9时结束循环,程序设计方法如下。
3.do…while循环
do…while循环非常类似于while循环。一般情况下,两者可以相互转换使用。它们之间的差别在于while循环的测试条件在每一次循环开始时执行,而do…while循环的测试条件在每一次循环体结束时进行判断。do…while语法的一般格式如下。
do
{
语句序列;
}
while(条件表达式);
当程序执行到do后,立即执行循环体中的语句序列,然后再对条件表达式进行测试。若条件表达式的值为真(true),则返回do语句重复循环,否则退出循环执行while语句后面的语句。例如下列代码所示。
4.foreach循环
foreach循环主要应用于遍历数据集(如数组、集合、文件夹中的文件或数据表等)的场景中。其语法格式如下。
foreach(类型变量名in数据集名)
{
循环体语句;
}
foreach语句中的“类型”必须与数组的类型一致,“变量名”是一个循环变量,在循环中,该变量依次获取数据集中各元素的值。这种操作常被称为“遍历”操作,特别是数据集中不易确定有多少个数据时,使用这种foreach语句就很方便。
例如下列代码所示。
又如,下列语句定义了一个无返回值的方法DelTemp,该方法用于删除指定文件夹下的所有文件。
5.循环的嵌套
若一个循环结构中包含有另一个循环,则称为“循环的嵌套”,这种语法结构也称为“多重循环”结构。循环嵌套的层数理论上无限制,但嵌套层数过多会占用大量的系统资源。
使用多重循环结构时需要注意循环语句所在循环的层次,内循环必须完全包含在外循环中。
【演练4-4】使用for循环嵌套实现在标签控件中显示如图4-4所示的“九九乘法表”。
图4-4 程序运行结果
(1)问题分析
本例可以使用双重循环来完成乘法表输出的问题,外层循环(i循环)决定第1个操作数。内层循环(j循环)决定了第2个操作数。当i=1时,内循环分别产生1×1、1×2、1×3…等。当i=2时内循环分别产生2×1、2×2、2×3…等,内外循环各循环9次,在屏幕上就能排列出9行9列的乘法表。
为了使页面美观,本例使用了HTML标记语言中的空格( ;)和换行标记<br/>。
(2)设计Web页面
新建一个ASP.NET网站,切换到设计视图,向Default.aspx页面中添加需要的文字和一个标签控件Label1,适当调整各对象的大小及位置。
(3)编写事件代码
Web页面载入时执行的事件代码如下。
4.1.4 使用类文件和类库
类文件是添加到网站中的一种独立的代码集合,其中通常包含了关于程序中所涉及的对象的一些定义(对象的属性、方法和事件等)和对数据库的操作(对数据库的增、删、改、查),也可以包含一些应用程序的业务逻辑实现。程序运行时可在控件的事件处理程序中创建对象的实例,以方便保存数据或调用类文件中定义的方法完成数据操作和业务逻辑的实现。
类库中包含的内容与类文件基本相同,只是类库需要单独创建,编译后将生成一个.dll文件(动态链接库文件)。类库不隶属于网站项目,只能被网站引用。类库被引用后便可在网站中使用其中定义的对象和方法。例如,可以将常用的数据库连接、增、删、改、查等操作设计成一个类库,经编译后生成.dll文件。之后,需要操作数据库时只要引用该类库即可,不再需要编写任何代码。
1.向网站中添加类文件
向网站中添加类项的方法与添加Web窗体的方法十分相似。在解决方案资源管理器中右击网站名称,在弹出的快捷菜单中选择“添加”→“添加新项”命令,在如图4-5所示的“添加新项”对话框中选择“类”模板,并为类文件命名后单击“添加”按钮。如果是首次向网站中添加类文件,系统将弹出信息框提示用户是否将类文件存放在App_Code专用文件夹中,一般应选择“是”。
图4-5 添加类文件
【演练4-5】设计一个能根据用户输入的商品编号和数量,计算总价并显示清单的程序。
要求程序的核心功能由类文件提供的方法来实现,商品库数据保存在文本文件中,当输入的商品编号不存在或未输入编号、数量时能给出提示,如图4-6~图4-8所示。程序正确运行时的界面如图4-9所示。
图4-6 编号不存在
图4-7 编号、数量不能为空
图4-8 数据格式错误
图4-9 程序正确运行的结果
程序设计步骤如下。
(1)设计程序界面
新建一个ASP.NET空网站,向网站中添加一个Web窗体页面Default.aspx。向页面中添加两个文本框、一个按钮控件和一个用于显示清单或提示信息的标签控件。适当调整各控件的大小及位置。
设置两个文本框的ID属性分别为txtNo(编号)和txtNum(数量);设置按钮控件的ID属性为btnOK,Text属性为“确定”;设置标签控件的ID属性为lblResult,Text属性为空。
(2)创建数据文件和类文件
在解决方案资源管理器中右击网站名称,在弹出的快捷菜单中选择“添加”→“添加新项”命令,在弹出的对话框中选择“类”模板并将类文件命名为Product.cs,单击“添加”按钮。当系统询问是否要创建App_Code文件夹时,选择“是”。
再次右击网站名称,在弹出的快捷菜单中选择“添加”→“添加ASP.NET文件夹”→App_Data命令,向网站中添加一个用于存放数据文件的App_Data文件夹。
用Windows记事本程序创建一个名为Data.txt的文本文件。如图4-10所示,按第1行为编号,第2行为名称,第3行为单价的格式逐个输入所有商品的数据。
(3)编写类文件代码
在解决方案资源管理器中双击打开类文件Product.cs,按如下所示编写其代码。
图4-10 创建商品数据文件
(4)编写事件代码
Default.aspx中“确定”按钮被单击时执行的事件处理程序代码如下。
说明:本例程序由Web页面Default.aspx和Product类文件两个层次组成。这种分层设计方式可以较好地实现“高内聚、低耦合”的设计指导思想,对程序维护和扩展更加有利。
1)Web页面负责提供用户输入和结果显示界面,负责验证用户输入的有效性,负责根据用户需要向Product类提出数据请求。
2)Product类提供的GetData()方法负责从文本文件中(数据库)提取所有数据,并根据Default.aspx传递过来的参数返回用户所需数据(包括计算结果);CheckNo()方法负责检查Default.aspx传递过来的“编号”参数是否存在于数据集中。
2.引用类库
类库是包含了一些特定功能(如数据库操作、某种业务逻辑的实现等)的应用程序的封装。类库可以由程序员根据实际需要自行编写代码创建,也可以直接引用第三方提供的已编译完成的.dll文件。Internet中存在大量优秀的、由第三方编写并封装的.dll格式的类库或组件文件,直接引用这些类库可以非常轻松地完成一些看似非常复杂的工作。
例如,当需要在没有安装MicrosoftWord软件的Web服务器中,对Word文档进行读、写、插图、插表和合并文档等操作时,就可以借助由第三方提供的、功能十分强大的Aspose.Words.dll来实现。
【演练4-6】通过引用Aspose.Words.dll,实现在没有安装Microsoft Word软件的Web服务器中合并两个Word文档。图4-11和图4-12所示为合并前的两个Word文档,图4-13所示为合并后的结果。
图4-11 文档1的内容
图4-12 文档2的内容
图4-13 合并后的结果
程序设计步骤如下。
(1)设计程序界面
新建一个ASP.NET空网站,向网站中添加一个Web窗体页Default.aspx。向Default.aspx中添加一个按钮控件。
(2)添加对第三方dll文件的引用
在解决方案资源管理器中右击网站名称,在弹出的快捷菜单中选择“添加”→“引用”命令,在弹出的“引用管理器”对话框中单击最下方的“浏览”按钮,在弹出的如图4-14所示的“选择要引用的文件”对话框中选择需要引用的.dll文件,然后单击“添加”按钮。返回“引用管理器”对话框,如图4-15所示,单击“确定”按钮完成引用操作。引用完成后系统会在网站中自动创建一个名为Bin的文件夹,并将.dll文件复制到其中。
图4-14 选择要引用的.dll文件
图4-15 添加引用
(3)编写程序代码
在Default.aspx的设计视图中双击已添加到页面中的按钮控件Button1,进入页面的代码编辑窗口。按照以下所示编写程序代码。
为了编写程序的方便,需要在引用区使用using语句添加对Aspose.Words命名空间的引用。
usingAspose.Words;
编写按钮被单击时执行的事件处理程序代码如下。
4.2 创建和使用动态控件
存放在工具箱中的各种控件都是以“类”的形式出现的。例如,工具箱中的按钮控件图标就代表了各种表现形式的所有按钮。也就是说工具箱中的控件表现的是一种“类型”,将其添加到窗体的操作实际上是完成了“类的实例化”,即将抽象的类型转换成实际的对象。
由于控件是控件类的实例化结果,自然可以在程序运行中使用代码动态地创建、显示和操作控件。通常将由代码根据实际需要动态创建的控件称为“动态控件”。
4.2.1 创建动态控件
创建动态控件首先需要实例化一个控件类,得到对应的控件类对象。然后,根据需要通过委托创建该对象的事件。
1.实例化控件类
控件类的实例化与普通类的实例化步骤完全相同,其语法格式如下。
控件类名对象名=new控件类名;
例如,下列语句用于实例化一个Button类对象。
Button btn=new Button();
通过控件类实例化得到的控件对象,可以像处理普通控件一样设置其初始属性。举例如下。
Button btn=new Button(); //btn为Button类的一个实例化对象
btn.Text="确定"; //设置对象的属性
2.创建控件类对象的事件
通过实例化得到控件类对象后,通常需要使用带有两个参数的EventHandler委托来定义对象的某个事件。
举例如下。
Button btn=new Button(); //实例化一个Button类
btn.Click+=new EventHandler(btn_Click); //声明Button类对象btn的单击(Click)事件
上述代码声明了btn对象的一个Click事件,事件处理程序以下列形式表示。
private voidbtn_Click(object sender,EventArgs e)
参数sender表示触发该事件的具体对象,参数e用于传递事件的细节。
概括地说,使用EventHandler委托声明对象事件的语法格式如下。
对象名.事件名+=newEventHandler(事件处理程序名);
例如,声明某文本框对象txt的TextChanged事件可使用以下语句。
txt.TextChanged+=EventHandler(txt_TextChanged);
4.2.2 使用动态控件
动态控件创建后,需要通过窗体或某个容器控件的Controls类的Add方法,将其添加到指定位置。若需要访问动态控件的属性,则需要首先使用Controls类的Find方法找到控件,然后对查找的结果进行操作。
1.将动态控件添加到Web页面
将控件对象添加到窗体或某个容器控件中,需要使用Controls类的Add方法,其语法格式如下。
Controls.Add(对象名称);
如果希望将动态控件添加到某容器中,可使用以下所示的语法格式。
容器控件ID.Controls.Add(对象名称);
例如,下列代码可将一个按钮对象添加到窗体的指定位置。
Button btn=new Button(); //实例化一个按钮类对象btn
btn.Top=30; //按钮距窗体顶端30px
btn.Left=40; //按钮距窗体左侧40px
Controls.Add(btn); //将按钮对象btn显示到指定位置
2.访问动态控件的属性
访问控件对象的属性需要首先使用Controls类的Find方法查找控件,该方法所带的两个参数分别表示被查找控件的Name属性值和是否查找子控件。其语法格式如下。
Control[]结果集名称=Controls.Find("对象Name属性值",true/false)
Find方法的返回值为一个控件集合(存放所有找到的控件)。
如果希望访问结果集中第n个控件的某属性值,可使用以下代码。
变量类型变量名=结果集名称[n-1].属性名; //结果集的索引值从零开始
【演练4-7】要求程序运行时能根据用户指定的行列数动态地创建HTML表格,并将单元格所在的行列坐标自动显示出来。然后在表格的最后追加4行,并要求每行生成一个通栏的单元格,要求在单元格中通过代码添加一个超链接控件HyperLink,该控件的文本、超链接地址和目标框架等属性均通过代码进行设置,当用户单击HyperLink控件时,页面能跳转到预设的URL。若用户未指定表格的行、列数而直接单击“生成表格”按钮,程序将给出错误提示,运行结果如图4-16所示。
图4-16 动态生成的表格和超链接控件
程序设计步骤如下。
(1)设计Web页面
新建一个ASP.NET空网站,向网站中添加Default.aspx页面,输入用于表示各控件作用的说明文字;向页面中添加两个文本框控件TextBox1和TextBox2;添加一个按钮控件But-ton1和一个Web服务器表格控件Table1(注意,应从工具箱的“标准”选项卡中添加,不要从HTML选项卡中添加),适当调整各控件的大小和位置。
(2)编写事件代码
1)页面载入时执行的事件过程代码如下。
2)“生成表格”按钮被单击时执行的事件过程代码如下。
说明:本例中涉及的技术在动态网站设计中经常用到,只是产生控件的数量及控件的属性值(如HyperLink控件的文本、超链接地址和目标框架等)一般是通过后台管理程序存放在数据库中的,前台程序(用户访问的Web页面)读取存放在数据库中的这些数据后,赋值给相应的对象。
4.3 创建和使用自定义控件
在Visual Studio中,用户除了可以使用系统提供的各种HTML控件和Web服务器控件外,还可以根据自己的实际需要创建具有事件处理能力的Web用户控件(也称为“自定义控件”)。自定义控件创建后,可以在设计视图或程序运行时将其添加到页面中。
4.3.1 创建自定义控件
ASP.NET提供的HTML控件和Web服务器控件具有十分强大的功能,但它们并不能涵盖每一种情况。使用自定义控件可根据程序的需要方便地定义控件,且在设计自定义控件时所使用的编程技术与设计Web页面的技术完全相同,甚至只需对Web窗体(.aspx)进行简单的修改即可使之成为自定义控件。自定义控件文件名以ascx为扩展名进行标识。
一个自定义控件与一个完整的Web窗体相似,都包含一个用户界面和一个代码文件。在自定义控件上可以使用标准Web窗体上相同的HTML控件和Web服务器控件。例如,希望创建一个网站导航栏自定义控件,则可将若干ImageButton控件通过HTML表格进行布局,并创建这些ImageButton的事件处理程序即可。
自定义控件页与Web窗体页主要有以下两点区别。
1)自定义控件页只能以ascx为扩展名。
2)在自定义控件文件中不能包含<html><body>和<from>元素,这些元素应位于宿主页(引用自定义控件的Web窗体)中。
创建或打开一个ASP.NET网站,在解决方案资源管理器中右击网站名称,在弹出的快捷菜单中选择“添加”→“Web用户控件”命令,在弹出的对话框中指定自定义控件文件名后单击“确定”按钮。
在解决方案资源管理器中双击自定义控件文件名,可在设计区将其打开,单击设计区下方的“源”或“设计”选项,可在源视图和设计视图两种方式之间切换。也可以直接单击设计区上方的选项卡,在自定义控件、Web窗体及代码窗口之间直接进行切换。
创建自定义控件后,可以像对待其他Web窗体页面一样向自定义控件界面中添加各种HTML或Web标准控件,双击自定义控件界面中的标准控件可自动切换到代码窗口,在系统自动创建的事件框架中编写事件处理程序。
4.3.2 使用自定义控件
自定义控件的界面和事件处理程序编写完毕后,还必须将其放置在一个Web窗体页中才能使用。在设计视图中打开希望添加自定义控件的Web窗体页面。
1.程序设计时使用自定义控件
在解决方案资源管理器中,将设计完毕的自定义控件直接从解决方案资源管理器拖动到页面适当的位置。窗体设计器能自动向Web页面添加@Register指示符,使自定义控件成为Web窗体的一个组成部分。
此外,当自定义控件被添加到Web窗体中后,该控件的公共属性、事件和方法也将向Web窗体公开,并可以通过编程的方式来使用。
前面已介绍过编写自定义控件的方法与设计Web窗体页面的方法完全相同,唯一不同的是在自定义控件中不能有<html><body>和<form>元素。因此,只要将一个设计完毕的Web窗体页面中所有<html><body>和<form>元素删除,在源视图中将Web页面的@Page指示符改成@Control,在解决方案资源管理器中将文件扩展名改成ascx就可以了。同样的道理,也可以方便地将一个设计完毕的自定义控件改成一个独立的Web窗体页面。
2.程序运行时动态添加自定义控件
设计完毕的自定义控件可以像前面介绍的那样,在设计视图中将自定义控件拖动到Web页面中即可。自定义控件也可以在程序运行时通过代码动态地加载,这样就能根据实际需要向页面中添加不同的自定义控件,或通过循环向页面中添加若干个相同的自定义控件。
在实际应用中,通常需要在主Web页面中添加一个容器控件PlaceHolder,作为用户自定义控件的“占位”控件。在程序运行时通过代码创建一个自定义控件的实例,然后将自定义控件添加到容器控件中。
举例如下。
4.4 实训——设计一个加法练习程序
4.4.1 实训目的
通过上机操作掌握C#中结构化程序设计的基本方法;理解顺序结构和选择结构的基本概念;掌握if…else、switch语句的使用方法。通过本实训进一步理解使用C#创建ASP.NET网站的一般步骤和常用编程技巧。
4.4.2 实训要求
设计一个用于100以内的加法练习程序。如图4-17所示,程序启动后自动产生两个100以内的随机整数显示在屏幕上,用户输入算式的答案后单击“确定”按钮,程序将算式显示出来并通过“√”或“×”给出评判,对出错的算式以醒目形式显示。同时给出下一道题。
如果用户没有输入算式答案而直接单击了“确定”按钮,程序将显示如图4-18所示的出错提示。
图4-17 程序运行结果
当用户单击“结束”按钮时,屏幕上将显示如图4-19所示的总出题数、正确数、错误数和得分,其中得分计算方法为:得分=正确数/总数×100。
图4-18 显示出错信息
图4-19 显示统计信息
继续输入算式答案,并单击“确定”按钮,开始新一轮的加法练习。