visual c#.net 程序设计
DESCRIPTION
Visual C#.NET 程序设计. 第 8 章 维护数据 ( 二 ). 学习和实践的目标. 需求分析要求:增加、删除、修改与学生成绩相关的基础数据,即学生、学年、课程、教师、成绩比例和操作员。 本章将充分利用对象的继承性和多态性完成所有基础数据的增加、修改和删除。. 实现目标的知识点. 数组 跳转和循环控制 数据类型转换. 8.1 实现目标的步骤. 利用对象的继承性和多态性维护数据的步骤如图 8-1 所示。. 8.2 数组与循环控制处理. - PowerPoint PPT PresentationTRANSCRIPT
23/4/21 1
Visual C#.NET 程序设计
第 8 章 维护数据 ( 二 )
第 8 章 维护数据 ( 二 )
23/4/21 2
学习和实践的目标
需求分析要求:增加、删除、修改与学生成绩相关的基础数据,即学生、学年、课程、教师、成绩比例和操作员。
本章将充分利用对象的继承性和多态性完成所有基础数据的增加、修改和删除。
第 8 章 维护数据 ( 二 )
23/4/21 3
实现目标的知识点
数组 跳转和循环控制 数据类型转换
第 8 章 维护数据 ( 二 )
23/4/21 4
8.1 实现目标的步骤
利用对象的继承性和多态性维护数据的步骤如图 8-1 所示。
将 f rm增改学生 中的ShowDi al og和Modi fy方法要完成的工作上移至 f rm增改 中,使其惠及派生类
frm增改学生 frm增改
第 8 章 维护数据 ( 二 )
23/4/21 5
8.2 数组与循环控制处理 数据及其处理总是贯穿在应用程序的整个
开发过程中。相关的数据可以聚合成集。通过数据集的集中处理,可以极大地提高数据处理的灵活性和效率。
8.2.1 数组 以 System.Array 为基类型的数组是一种包含若
干元素的数据结构,是特殊的数据集合。 每个数组中包含的若干个元素都具有相同的数据
类型 , 可通过一个统一的数组变量名和下标(索引)来唯一地确定数组中的元素以进行访问。
C# 中的数组有一维数组、多维数组和交错数组。
第 8 章 维护数据 ( 二 )
23/4/21 6
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 一维数组的声明格式如下 :
数组类型 [] 数组变量 ; 数组类型可以为 .NET 平台下支持的任意
数据类型,如: Int16 、 Int32和Int64 等,它们都处于 System 命名空间中。假设事先已引入 System 命名空间。
如: Int32[] a;
第 8 章 维护数据 ( 二 )
23/4/21 7
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 数组类型属于引用类型,因此数组变量的
声明只是为数组实例的引用留出空间,实际的数组实例在运行时使用 new 运算符动态创建。如:
a=new Int32[10]; 以上语句才会使数组 a 成为实际上的、
物理上存在的整型数组,数组 a 将会包含 10个 Int32 型的元素。
第 8 章 维护数据 ( 二 )
23/4/21 8
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 new 运算符从真正意义上创建了数组,同
时也指定了新数组实例的长度 (length) ,它在该实例的生存期内是固定不变的。
数组元素的索引范围从 0 到 Length - 1 。 new 运算符自动将数组的元素初始化为它
们的默认值,例如将所有数值类型初始化为零,将所有引用类型初始化为 null 。
第 8 章 维护数据 ( 二 )
23/4/21 9
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 下面的控制台应用程序创建并初始化了一个
Int32 类型的一维数组,同时还在控制台上输出该数组中的内容:
using System; class Test { static void Main() { Int32[] a = new Int32[10]; for (Int32 i = 0; i < a.Length; i++)
a[i] = i * i;
第 8 章 维护数据 ( 二 )
23/4/21 10
8.2 数组与循环控制处理8.2.1 数组1 .一维数组
for (Int32 i = 0; i < a.Length; i++) { Console.Write ("a["+i+"] = "+a[i]+”
”); } } }
所生成的输出如下: a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16
a[5]=25 a[6]=36 a[7]=49 a[8]=64 a[9]=81
第 8 章 维护数据 ( 二 )
23/4/21 11
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 new 运算符还允许使用数组初始值设定项,
以指定数组元素的初始值。数组初始值设定项是在一个位于定界符 {} 之间的表达式列表。下面的示例分配并初始化具有三个元素的 Int32[] :
Int32[] a = new Int32[] {1, 2, 3};
第 8 章 维护数据 ( 二 )
23/4/21 12
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 注意数组的长度是从 {} 之间的表达式个数
推断出来的。对于局部变量和字段声明,可以进一步简写,不必再次声明数组类型。例如:
Int32[] a = {1, 2, 3}; 前面的两个示例都等效于下面的示例: Int32[] a = new Int32[3]; a[0] = 1; a[1] = 2; a[2] = 3;
第 8 章 维护数据 ( 二 )
23/4/21 13
8.2 数组与循环控制处理8.2.1 数组1 .一维数组 当一个数组创建表达式既包含显式维度长度,又包含数组初始值设定项时,长度必须是常量表达式,同时各嵌套级别的元素数目必须与相应的维度长度相匹配。参见以下示例:
Int32 i = 3; Int32[] x = new Int32[3] {0, 1, 2}; // 正确 Int32[] y = new Int32[i] {0, 1, 2}; // 错误 ,
i 不是常量 Int32[] z = new Int32[3] {0, 1, 2, 3}; //
错误 , 维度长度和一个数组初始值设定项不匹配
第 8 章 维护数据 ( 二 )
23/4/21 14
8.2 数组与循环控制处理8.2.1 数组2 .多维数组 数组类型的维数也称为数组类型的秩 (rank) ,它是
数组类型方括号之间的逗号个数加上 1 。例如: Int32[,]a1 = new Int32[10, 5]; // 分配一个二
维数组 Int32[,,]a2 = new Int32[10, 5, 2]; // 分配一
个三维数组 a1 数组包含 50 (10 × 5) 个元素, a2 数组包含
100 (10 × 5 × 2) 个元素。 多维数组的初始值设定项必须具有与数组维数同样多
的嵌套级别。最外面的嵌套级别对应于最左边的维度,而最里面的嵌套级别对应于最右边的维度。
第 8 章 维护数据 ( 二 )
23/4/21 15
8.2 数组与循环控制处理8.2.1 数组3 .交错数组 数组的元素类型不仅可以是 .NET 平台下支持
的任意数据类型任意类型,还可以是数组类型。数组元素的类型为数组时称之为交错数组 (jagged array) ,此时元素数组的长度不必全都相同。下面的示例分配一个由 Int32 数组组成的数组:
Int32[][] a = new Int32[3][]; a[0] = new Int32[10]; a[1] = new Int32[5]; a[2] = new Int32[7];
第 8 章 维护数据 ( 二 )
23/4/21 16
8.2 数组与循环控制处理
8.2.1 数组3 .交错数组
a[0] = new Int32[]{ 2,4,6,8,10,12,14,16,18,20 }; //10 个整数组成的数组
a[1] = new Int32[]{ 1,3,5,7,9 }; //5 个整数组成的数组
a[2] = new Int32[]{ 11,22,33,44,55,66,77 }; //7 个整数组成的数组。
第 8 章 维护数据 ( 二 )
23/4/21 17
8.2 数组与循环控制处理
8.2.2 循环控制结构 循环控制结构可以用于重复执行嵌入语
句。 C# 中的循环(迭代)语句有: while 语句 do 语句 for 语句 foreach 语句
第 8 章 维护数据 ( 二 )
23/4/21 18
8.2 数组与循环控制处理8.2.2 循环控制结构1 .while 语句 while 语句按不同条件不执行或至少执行一次语句块。 while 语句的一般格式为:
while ( 布尔表达式 ) { 语句块; }
while 语句按下列规则执行:① 计算布尔表达式。② 当布尔表达式值为 true 时,执行 while 语句中的语句块,
然后程序转到①。③ 当布尔表达式值为 false 时,结束循环。
第 8 章 维护数据 ( 二 )
23/4/21 19
8.2 数组与循环控制处理8.2.2 循环控制结构1 .while 语句 下面的控制台应用程序,利用 while 语句求
1+2+3+…+10 ,并在控制台上输出其和。代码如下: using System; class Sum { static void Main() { Int32 num=1,sum=0; while (num<11) { sum=sum+num; num++; } Console.WriteLine("1+2+3+...+10 ="+sum); } }
输出结果如下:1+2+3+...+10 =55
第 8 章 维护数据 ( 二 )
23/4/21 20
8.2 数组与循环控制处理8.2.2 循环控制结构2 . do 语句 do 语句按不同条件至少执行一次或多次语句块。 do 语句的一般格式为:
do { 语句块; } while (布尔表达式 ) ;
do 语句按下列规则执行:① 执行语句块一次。② 计算布尔表达式的值,当值为 true 时,程序转到①;否则,结束循环。
第 8 章 维护数据 ( 二 )
23/4/21 21
8.2 数组与循环控制处理8.2.2 循环控制结构 下面的控制台应用程序,利用 do…while 语句求
1+2+3+…+10 ,并在控制台上输出其和。代码如下: using System; class Sum { static void Main() { Int32 num=1,sum=0; do { sum=sum+num; num++; } while (num<11); Console.WriteLine("1+2+3+...+10 ="+sum); } }
输出结果同 while 语句。
第 8 章 维护数据 ( 二 )
23/4/21 22
8.2 数组与循环控制处理8.2.2 循环控制结构3 . for 语句 for 语句计算一个初始化表达式,然后,当某个条件
为真时,重复执行相关的嵌入语句并计算一个迭代表达式序列。 for 语句的一般格式为:
for( 初始化表达式 ; 终止条件布尔表达式 ; 步进语句表达式 )
{ 语句块; }
其中初始化表达式是为循环变量赋初值,可以有 1 个或多个,若有多个则用逗号隔开;终止条件布尔表达式是用来决定是否执行语句块;步进语句表达式是按规律改变初始表达式中循环变量的值。这三个表达式都是可选的,缺省某个表达式时,其后的“;”不能省。
第 8 章 维护数据 ( 二 )
23/4/21 23
8.2 数组与循环控制处理8.2.2 循环控制结构3 . for 语句 下列代码表达了三个表达式都缺省的情况:
for(;;) { 语句块; }
for 语句按如下规则执行: ① 执行初始化表达式,为循环变量赋初值。 ② 若没有终止条件布尔表达式,或终止条件布尔表达式值为 true 时,则直接执行大括号中的语句块,程序转向③;否则,结束循环。
③ 执行步进语句表达式,程序转向②。
第 8 章 维护数据 ( 二 )
23/4/21 24
8.2 数组与循环控制处理8.2.2 循环控制结构3 . for 语句 下面的控制台应用程序,利用 for 语句求 1+2+3+…
+10 ,并在控制台上输出其和。代码如下: using System; class Sum { static void Main() { Int32 num,sum; for(num=1,sum=0;num<11;num++)
{ sum=sum+num; } Console.WriteLine("1+2+3+...+10 ="+sum); } }
输出结果同 while 语句。
第 8 章 维护数据 ( 二 )
23/4/21 25
8.2 数组与循环控制处理8.2.2 循环控制结构4 . foreach 语句 foreach 语句用于遍历一个集合的元素,并对该集
合中的每个元素执行一次相关的语句块。 foreach 语句的一般格式为:
foreach ( 类型标识符 标识符 in 表达式 ) { 语句块 ; }
其中类型标识符和标识符用来声明变量,表达式的类型必须是集合类型,如果该表达式的值为 null ,则将引发异常。每执行一次语句块,循环变量就依次取集合中的一个元素代入其中。
第 8 章 维护数据 ( 二 )
23/4/21 26
8.2 数组与循环控制处理8.2.2 循环控制结构4 . foreach 语句 下面的控制台应用程序,用于按照元素的顺序打印出一个二维数组中的各个元素的值。代码如下:
using System; class Test { static void Main() { Double[,] values = {{1.2, 2.3, 3.4, 4.5},{5.6,
6.7, 7.8, 8.9}}; foreach (Double elementValue in values) Console.Write(" " + elementValue); Console.WriteLine(); } }
输出结果如下: 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9
第 8 章 维护数据 ( 二 )
23/4/21 27
8.2 数组与循环控制处理8.2.3 跳转语句 跳转语句用于无条件地在程序间转移控制权。 C# 中的跳转语句有:
break 语句 continue 语句 goto 语句 return 语句 throw 语句
跳转语句会将控制转到某个位置,这个位置就称为跳转语句的目标 (target) 。
当一个跳转语句出现在某个块内,而该跳转语句的目标在该块之外时,就称该跳转语句退出该块。虽然跳转语句可以将控制转到一个块外,但它永远不能将控制转到一个块的内部。
第 8 章 维护数据 ( 二 )
23/4/21 28
8.2 数组与循环控制处理8.2.3 跳转语句1 . break 语句 break 语句直接退出所属的 switch、while、 do、
for 或 foreach 语句。当程序遇到这一语句后,执行紧接在被终止执行的语句后面的语句。通常break 语句总是与 if 语句联在一起。即满足条件时便跳出循环。
当多个 switch、while、 do、 for 或 foreach 语句彼此嵌套时, break 语句只应用于最里层的语句。若需要穿越多个嵌套层,可使用 goto 语句。
break 语句不能退出 finally 块。当 break 语句出现在 finally 块中时,该 break 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。块外,但它永远不能将控制转到一个块的内部。
第 8 章 维护数据 ( 二 )
23/4/21 29
8.2 数组与循环控制处理8.2.3 跳转语句1 . break 语句 下面的控制台应用程序计算 1 ~ 100 之间的和 ,
当数超过 100 时终止循环。代码如下: using System; class Sum { static void Main() { Int32 num=1,sum=0; while (true) { sum=sum+num; num++; if (num>100) break; } Console.WriteLine("1+2+3+...+100
="+sum); } }
输出结果如下:1+2+3+...+100
=5050
第 8 章 维护数据 ( 二 )
23/4/21 30
8.2 数组与循环控制处理8.2.3 跳转语句2 . continue 语句 continue 语句直接结束封闭它的 while、 do、 for 或 foreach 语句的本次循环,进入下一轮循环。它与前面提到的 break 语句不同,它并不终止整个循环的执行,而仅仅终止当前这一次循环的运行。
如果 continue 语句不是由 while、 do、 for 或 foreach 语句所封闭的,则发生编译时错误。
当多个 while、 do、 for 或 foreach 语句互相嵌套时, continue 语句只应用于最里层的那个语句。若需要穿越多个嵌套层,可使用 goto 语句。
continue 语句不能退出 finally 块。当 continue 语句出现在 finally 块中时,该 continue 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。
第 8 章 维护数据 ( 二 )
23/4/21 31
8.2 数组与循环控制处理8.2.3 跳转语句2 . continue 语句 下面的控制台应用程序计算数 1 ~ 100 之间的偶
数和。代码如下: using System; class Sum { static void Main() { Int32 num,sum=0; for(num=1;num<101;num++) { if (num%2!=0) continue; sum=sum+num; } Console.WriteLine("1到 100 之间的偶数和为
"+sum); } }
输出结果如下:1 到 100 之间的偶数和为
2550
第 8 章 维护数据 ( 二 )
23/4/21 32
8.2 数组与循环控制处理8.2.3 跳转语句3 . goto 语句 goto 语句将控制无条件的转移到由标签标记的语句。
它能用来跳出循环和 switch 语句。 如果当前函数成员中不存在具有给定名称的标签,或者如果 goto 语句不在该标签的范围内,则发生编译时错误。标号与 goto 语句必须处在同一个函数中。此规则允许使用 goto 语句将控制转移“出”嵌套范围,但是不允许将控制转移“进”嵌套范围。
goto 语句不能退出 finally 块。当 goto 语句出现在 finally 块中时,该 goto 语句的目标必须位于同一个 finally 块中,否则将发生编译时错误。
第 8 章 维护数据 ( 二 )
23/4/21 33
8.2 数组与循环控制处理8.2.3 跳转语句3 . goto 语句 下面是一个控制台应用程序示例:
using System; class Test { static void Main(string[] args) { string[,] table = {{"Red", "Blue", "Green"},
{"Monday", "Wednesday", "Friday"}}; foreach (string str in table) { int row, colm; for (row = 0; row <= 1; ++row) for (colm = 0; colm <= 2; ++colm) if (str == table[row,colm]) goto done;
第 8 章 维护数据 ( 二 )
23/4/21 34
8.2 数组与循环控制处理8.2.3 跳转语句 3 . goto 语句
Console.WriteLine(“{0} 未找到” , str);//显示 str 的内容未找到 continue; done: Console.WriteLine("在 [{1}][{2}] 位置找到 {0}", str, row, colm); } } }
输出结果如下: 在 [0][0] 位置找到 Red 在 [0][1] 位置找到 Blue 在 [0][2] 位置找到 Green 在 [1][0] 位置找到 Monday 在 [1][1] 位置找到 Wednesday 在 [1][2] 位置找到 Friday
第 8 章 维护数据 ( 二 )
23/4/21 35
8.2 数组与循环控制处理8.2.3 跳转语句 4 . return 语句 return 语句将控制返回到包含 return 语句的函数
成员的调用方。 若函数成员没有返回类型,则 return 语句后不带任何表达式;或函数成员有返回类型,则 return 语句后的表达式的计算结果,必须与函数成员返回类型一致。
return 语句出现在 finally 块中会造成编译时错误。
下面是一个控制台应用程序示例: using System; class Test { static Int64 sum(Int32 num)
第 8 章 维护数据 ( 二 )
23/4/21 36
8.2 数组与循环控制处理8.2.3 跳转语句 4 . return 语句
{ Int64 mysum=0; for (Int32 i = 1; i <=num; i++) mysum = mysum + i; return mysum; } static void Main(string[] args) { Console.WriteLine("从 1 到 100
的和为 "+sum(100)); } }
输出结果如下:从 1 到 100 的和为 50505 . throw 语句 throw 语句引发一个异常。
第 8 章 维护数据 ( 二 )
23/4/21 37
8.3 数据类型的转换
类型转换是将数据从一种类型更改为另一种类型的过程。例如,可以将字符串“ 1234”转换为一个数字。可以将任意类型的数据转换为 String 类型。
某些类型转换永远不会成功。例如,字符串 " 张三 "不能转换为整型数据。
第 8 章 维护数据 ( 二 )
23/4/21 38
8.3 数据类型的转换
1 .基本概念 类型转换有可能扩大,也有可能收缩。 扩大转换就是指将数据类型 A 的值转换
为数据类型 B,并且保证数据类型 B可以容纳数据类型 A 的任何可能值,例如,转换 Int32 型为 Int64 型,转换派生类型为基类型。
收缩转换就是指将数据类型 A 的值转换为数据类型 B,但数据类型 B 无法容纳数据类型 A 的某些可能值,例如,转换Int64 型为 Int32 型,转换基类型为派生类型。
第 8 章 维护数据 ( 二 )
23/4/21 39
8.3 数据类型的转换
1 .基本概念 扩大转换永远不会溢出,并且总是成功
的;而收缩转换必然往往伴有信息的丢失,并有可能失败。
两种转换类型都可以是显式(使用数据类型标识符)或隐式(不使用数据类型标识符)的。例如:
Int32 a = 123; Int64 b = a; // 隐式转换 Int32 c = (Int32) b; // 显式转换
第 8 章 维护数据 ( 二 )
23/4/21 40
8.3 数据类型的转换
1 .基本概念 有效的显式转换即使会导致信息的丢失,
也始终是成功的。而隐式转换只有在转换过程不丢失数据的情况下才能成功;否则,它们就会失败并生成编译或运行时错误。
.NET 类库中的 Form 窗体类有一个属性 Controls ,这是一个集合,其中元素是窗体上的所有控件,如: TextBox 。窗体上的控件都以 Control 为基类。
第 8 章 维护数据 ( 二 )
23/4/21 41
8.3 数据类型的转换
1 .基本概念 下面代码将窗体上的一般控件显式收缩转
换为 TextBox 控件。 foreach(Control ctl in Controls) { //从 Control 基类显式转变为 TextBox派
生类 TextBox tx = (TextBox)ctl; }
执行中许多非 TextBox 控件向 TextBox控件转换时会失败。
第 8 章 维护数据 ( 二 )
23/4/21 42
8.3 数据类型的转换
1 .基本概念 当原始数据类型在目标转换类型中没有明显
的对应类型时,就会发生丢失数据的转换。例如,字符串 "Fred" 不能转换为一个数字。在这些情况下,类型转换函数将返回一个默认值。对于字符串类型,默认值为 "";对于整型类型,默认值为数字 0 。
常用的 ToString方法就是显式转换的典型代表,因为它是所有数据类型的根类 object的方法,所以所有数据类型都可以向字符串类型转换。
第 8 章 维护数据 ( 二 )
23/4/21 43
8.3 数据类型的转换
2 . Convert 类 Convert 是一个专用来将一个基本数据类
型转换为另一个基本数据类型的类,因为是静态类,不需要实例化就可以直接使用。
例如: Int64 I = 123; Int32 i = Convert.ToInt32(I);
第 8 章 维护数据 ( 二 )
23/4/21 44
8.3 数据类型的转换
3 .装箱和拆箱 装箱和拆箱的概念是 C# 的类型系统的核心。它在值类型和引用类型之间的架起了一座桥梁,使得任何值类型的值都可以转换为 object 类型的值,反过来转换也可以。从值类型转换为引用类型称为装箱,反之,称为拆箱。
装箱和拆箱使我们能够统一地来考察类型系统,其中任何类型的值最终都可以按对象处理
第 8 章 维护数据 ( 二 )
23/4/21 45
8.3 数据类型的转换
3 .装箱和拆箱 下面是装箱和拆箱转换的示例,代码如下:
Int32 i = 10; //i 是值类型 object o = i; //装箱 i = (Int32)o; //拆箱 MessageBox.Show(i.ToString());// 整型
数转换成字符串 装箱操作如图 8-2 所示 ,拆箱操作如图 8-3 所
示。
第 8 章 维护数据 ( 二 )
23/4/21 46
8.3 数据类型的转换
3 .装箱和拆箱 图 8-2装箱操作 图 8-3拆箱操作
i: Int32
10
i: Int32
10
o: object
拆箱
i: Int32
10
Int32
10o:object
装箱
第 8 章 维护数据 ( 二 )
23/4/21 47
8.3 数据类型的转换
3 .装箱和拆箱 一个装箱操作包括两个步骤:首先分配
一个对象实例,然后将值类型的值复制到该实例中。
一个拆箱操作包括两个步骤:首先检查对象实例是否为给定值类型的一个装了箱的值,然后将该值从实例中复制出来。
第 8 章 维护数据 ( 二 )
23/4/21 48
8.4 改造 ShowDialog方法
我们已经建立了数据维护对象体系,如图 8-4 所示。
第 8 章 维护数据 ( 二 )
23/4/21 49
8.4 改造 ShowDialog方法
实现了 frm 增改学生的 ShowDialog方法。
类似地,要为 frm 增改课程等实现ShowDialog方法。不仅工作量较大,且容易出错,将来也不利于进行代码维护。
若能在 frm 增改中实现 ShowDialog方法,则可以惠及其派生类,起到“一劳永逸”的功效。
第 8 章 维护数据 ( 二 )
23/4/21 50
8.4 改造 ShowDialog方法
8.4.1 提示必要信息 在 frm 增改中实现 ShowDialog方法所
面临的最大问题是:不知道其派生类中需要处理的输入控件。而处理的关键是要抓住被处理的控件。
窗体对象包含有一个控件集合 Controls ,控件集合 Controls 中包含了窗体上所有的控件( Control ),如 TextBox和DateTimePicker 控件等。如果能对Controls 中所有的 Control 进行遍历,就能进行适当的处理了。
第 8 章 维护数据 ( 二 )
23/4/21 51
8.4 改造 ShowDialog方法
8.4.1 提示必要信息 像 foreach这样的循环控制结构可以有效地解决遍历
问题。下面是完成后的 frm 增改的 ShowDialog方法。
public virtual void ShowDialog(DataGridView dgv区域 ,Boolean bAdd )
{ …… // 循环处理当前窗体上所有输入控件 foreach (Control ctl in Controls) { // 初始化输入控件的内容 String str 控件类型 =ctl.Name.ToString().Substring(0,
3);//前三个字符反映控件类型 switch (str 控件类型 ) { case "txt": case "cmb": case "dtp":
第 8 章 维护数据 ( 二 )
23/4/21 52
8.4 改造 ShowDialog方法
8.4.1 提示必要信息
if (bAdd) //清空各个输入对象 ctl.Text = null; else { //保证有记录可以修改 if (dgv区域 .RowCount <= 0) { MessageBox.Show("无记录可以修
改! "); return; }
第 8 章 维护数据 ( 二 )
23/4/21 53
8.4 改造 ShowDialog方法
8.4.1 提示必要信息 //根据所选记录初始化输入对象 // 控件类型字符后面为控件名称,恰好为数据区域栏目名称和数据库字段名称
String str 控件名称 = ctl.Name.ToString().Substring(3);
ctl.Text = dgv区域 .CurrentRow.Cells[str 控件名称 ].Value.ToString();
} break; } } //调出模式对话框 ShowDialog(); }
第 8 章 维护数据 ( 二 )
23/4/21 54
8.4 改造 ShowDialog方法
8.4.2 控制文本输入长度 不论是增加还是修改操作,其结果都要存入
数据库。若输入的数据长度超过了实际数据库对应字段的长度,则会出现异常。所以有必要对所有输入控件设置符合要求的可输入长度。例如,把 TextBox文本控件的MaxLength 属性值设置为实际数据库对应字段的长度。有两种方法可以实现: 一种是在控件所在窗体类(如 frm 增改学生)
中进行设置。 一种是在控件所在窗体类的基类(如 frm 增
改)中进行设置。
第 8 章 维护数据 ( 二 )
23/4/21 55
8.4 改造 ShowDialog方法
8.4.2 控制文本输入长度 前一种方法需要对每一个窗体的控件进行修改,效
率不高,后一种方法优势是明显的。 专门设计一个方法 SetMaxLength ,根据数据库
表中字符串字段和数值字段的大小来设置 TextBox和 ComboBox的MaxLength 属性,在 frm 增改的 ShowDialog 中调用。
虽然TextBox、 ComboBox、 DateTimePicker和CheckBox 等控件的基类都是 Control ,但只有TextBox和 ComboBox有MaxLength 属性,可以对 Control 集合进行迭代处理,然后进行从Control向 TextBox或 ComboBox 的转换。
第 8 章 维护数据 ( 二 )
23/4/21 56
8.5 改造 Modify 方法
8.5.1 更新数据库 更新数据库的代码见 P143 上重写的
Modify()方法,关键是遍历每一个Control 控件,形成标准的 Insert或Update 语句。
第 8 章 维护数据 ( 二 )
23/4/21 57
8.5 改造 Modify 方法
8.5.2 刷新浏览数据
增加和修改的结果已经存入了数据库,还需要及时地反映在浏览对象中供用户参考。因为 DataGridView 控件是和 DataSet 中的一个表绑定的,所以只要修改 DataSet 中的表就可以达到目标。
第 8 章 维护数据 ( 二 )
23/4/21 58
8.6 隐藏浏览对象中的指定栏目
frm浏览已经可以将相关数据展现出来了。美中不足的是,起表间关联作用的主键和外键(含有 ID 的字段,例如,学生 ID )也显示出来了。对用户而言这是不需要的。
将隐藏 ID栏目的函数命名为 HideIDColumns ,通过DataGridView 类型的参数“ dgv区域”传递要处理的区域。检查“ dgv区域”中的每一个栏目,若栏目的名称含有 ID 字样,则使其不可见。
第 8 章 维护数据 ( 二 )
23/4/21 59
8.6 隐藏浏览对象中的指定栏目
/// <summary> /// 将带 ID 的字段隐藏起来 /// </summary> /// <param name="dgv区域 "></param> private void HideIDColumns(DataGridView dgv区域 ) { if (dgv区域 .DataMember != "") { //检查每一个栏目,若栏目的名字含有 ID 字样,则隐藏 foreach (DataGridViewColumn clmn in dgv区域 .Columns)
if (clmn.Name.IndexOf("ID") >= 0) clmn.Visible = false; } }
第 8 章 维护数据 ( 二 )
23/4/21 60
8.6 隐藏浏览对象中的指定栏目
调用 HideIDColumns 过程的时机是上、下两个区域绑定的数据成员变化时。 //" 上区域 "显示的数据表变化时自动执行 private void dgv 上区域 _DataMemberChanged(object sender,
EventArgs e) { HideIDColumns(dgv 上区域 );// 将带 ID 的字段隐藏起来 } //" 下区域 "显示的数据表变化时自动执行 private void dgv 下区域 _DataMemberChanged(object sender,
EventArgs e) { HideIDColumns(dgv 下区域 );// 将带 ID 的字段隐藏起来 }
第 8 章 维护数据 ( 二 )
23/4/21 61
习 题
一、简答题 1 .循环控制结构有几种?各有什么特
点? 2 .如果事先知道循环次数,选用哪种
循环结构比较好? 3 .在什么场合使用数组比较好? 4 .在系统代码中找出数据转换的例子,
指出是隐式转换还是显示转换,是扩大转换还是收缩转换。
第 8 章 维护数据 ( 二 )
23/4/21 62
习 题二、操作题1 . frm 登录通过输入账户(用户名和密码)来验证用户的合法性,同时为合法用户提供修改密码的能力。设计并实现 frm 登录类。
2 .将 frm 增改中将修改内容反映在浏览的 dgv区域中的 foreach代码改为等价的 for代码。
// 将修改内容反映在浏览的 dgv区域中 foreach (Control ctl in Controls) { //前三个字符反映控件类型 String str 控件类型 =
ctl.Name.ToString().Substring(0, 3); switch (str 控件类型 )
第 8 章 维护数据 ( 二 )
23/4/21 63
习 题
二、操作题 { case "txt": case "cmb": case "dtp": // 控件类型字符后面为控件名称,恰好为数据区域栏目名称和数据库字段名称 String str 字段名 = ctl.Name.ToString().Substring(3); ds.Tables[dgv区域 .DataMember].Rows[dgv区域 .CurrentRow.Index] [str 字段名 ]=ctl.Text; break; } }
第 8 章 维护数据 ( 二 )
23/4/21 64
习 题
二、操作题3 .编码实现 8.4.2小节要求的控制文本
输入长度的 SetMaxLength方法,并通过 frm 增改的 ShowDialog方法调用。