CS架构断开式应用程序设计入门教程.ppt_第1页
CS架构断开式应用程序设计入门教程.ppt_第2页
CS架构断开式应用程序设计入门教程.ppt_第3页
CS架构断开式应用程序设计入门教程.ppt_第4页
CS架构断开式应用程序设计入门教程.ppt_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第十章 数据库应用程序开发,ADO.Net 程序实现典型的数据库应用程序开发。 数据库连接 数据加载 数据的简单和复杂绑定 对DataSet数据浏览、插入、删除、确认和取消 DataSet的表达式列和数据检索 DataSet中数据表的关联 对数据库的更新:CommandBuilder的更新机制 报表设计-CrystalReport,SQL Server基本数据准备:,建立数据库teaching 建立下列数据表: Students:学生表(id,name,classid) Grade:成绩表(id,subid,grade) Classes:班级表(classid,name),1.1 ADO.Ne

2、tADO/OLE DB和ODBC关系图,VC+,VB,Delphi,ADO,OLE DB,ODBC,RDBMS,RDBMS,E-Mail,Directory Service,ADO.NET结构,1.2 实例分析:设计一个Form实现对数据表students、subjects和grade编辑和浏览功能examplea1,程序设计的两种方式 自编程序设计方式:自编程序实例化dataset等对象、设置属性、动态连接数据库、实现数据绑定、数据表关联等。 可视化设计方式:设计阶段通过添加组件,设置组件属性完成数据库的连接、数据绑定以及数据表的关联等,然后由系统生成部分程序。,1.2.1 自编程序方式,一

3、)把数据库中数据表数据显示在控件中 1)连接数据库:teaching (SQL Server) 2)数据库中数据载入DataSet:加载students 3)DataSet中数据和控件的绑定:id和TextBox的绑定,1)连接数据库:teaching (SQL Server),using System.Data.OleDb; private DataSet dataSet; private OleDbConnection oleDbConnection; private OleDbDataAdapter oleDbDataAdapter; private void ConnectDB() o

4、leDbConnection = new OleDbConnection(Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=teaching); oleDbConnection.Open(); OleDbConnection中连接字符串:新建teaching.udl文件,双击后进入oleDB数据链接属性编辑,连接对应数据库并成功进行测试连接后,关闭窗口后teaching.udl中包含了连接字符串。,2)数据库中数据载入DataSet:加载students,privat

5、e void LoadData() oleDbDataAdapter = new OleDbDataAdapter(select * from students, oleDbConnection); dataSet = new DataSet(); oleDbDataAdapter.Fill(dataSet, students); DataSet本身没有从数据库加载数据的能力,必须通过OleDbDataAdapter提供的Fill方法进行加载。 在Fill过程中,若dataSet中没有students,则会自动建立,并把“select * from students”结果载入。,3)DataS

6、et中数据和控件的绑定:id和TextBox的绑定,private void BindingControls() textBox1.DataBindings.Add(text, dataSet, “students.id); textBox1的Text属性和dataSet中students表的id字段进行绑定。 绑定的结果是textBox1的值和dataSet中students表的id值会同步变化。 在Form的load事件中执行下列语句:ConnectDB();LoadData();BindingControls();,二)复杂绑定:classid数据取自classes表,提供选择功能。,L

7、oadData中增加下列程序 oleDbDataAdapter.SelectCommand = new OleDbCommand(select * from classes,oleDbConnection); oleDbDataAdapter.Fill(dataSet, classes); 在BindControls中增加下列程序: comboBox1.DataSource = dataSet.Tablesclasses; ; comboBox1.DisplayMember=name; comboBox1.ValueMember = classid; comboBox1.DataBinding

8、s.Add(selectedValue, dataSet, students.classid);,三)加入浏览功能,DataSet中的Table和数据库中数据表一样,没有行顺序的概念,所有没有提供行号定位的方法和属性 当一个数据表数据绑定在Form上的若干控件后,由其BindingContext成员管理从Control类继承的任意对象的 BindingManagerBase对象集合,通过设置其属性Position来控制当前显示的行: this.BindingContextdataSet, students.Position += 1; 注意students和控件的绑定方式不能写成下列形式,这将

9、使Form仅显示首行内容,而无法通过上述方式定位到其他行。 textBox1.DataBindings.Add(text, dataSet.Tablesstudents, id); 首行对应Position=0,当Position=0,再-1属性值将不变。当Position=总行数-1,再加1同样值不变。,绑定方式一致性:DataGridView,TextBox同步以及BindingContext的下标一致性,匹配一: dataGridView1.DataSource = dataset; dataGridView1.DataMember = t_major; textBox1.DataBin

10、dings.Add(text, dataSet, “students.id); this.BindingContextdataSet, students.Position 0; 匹配二: dataGridView1.DataSource = dataset.Tables“students; textBox1.DataBindings.Add(text,dataset.Tables“students,“id); this.BindingContextdataset.Tables“students.Position = 0; 关键在于三个语句中的Datasource参数的一致性,即dataGrid

11、View.Datasource、绑定语句中的第二个参数和BindingContext中的第一个下标必须一致。,四)使用绑定对DataSet数据表进行插入和删除,插入: this.BindingContextdataSet, students.EndCurrentEdit(); this.BindingContextdataSet, students.AddNew(); 删除: this.BindingContextdataSet, students.RemoveAt(this.BindingContextdataSet, students.Position); 取消当前行的修改: this.B

12、indingContextdataSet, students.CancelCurrentEdit();,五)通过控件输入的DataSet数据的取消和确认功能,控件输入数据与DataSet数据同步: this.BindingContextdataSet, “students”.Position值变化或调用this.BindingContextdataSet, “students”.EndCurrentEdit()后,界面控件数据才写入DataSet。 取消修改: dataSet.RejectChanges():取消dataSet创建或调用dataSet.AcceptChanges()以后对dat

13、aSet所作的修改。 接收修改: dataSet.AcceptChanges():接收对dataSet中数据所做的修改。 dataSet中各表及表中各行对象均有取消和接受修改的上述两个方法,区别是其作用的对象范围不同。,六)把DataSet数据存入数据库,更新数据库中数据表的唯一途径是执行SQL的insert、update或delete语句,dataSet中数据的修改(表的增、删、改),要反映到数据库中,必须根据修改情况产生并执行相应的SQL语句。所以要根据对DataSet数据表的修改更新对应数据库中的数据表,必须完成下列三部分工作: 标记DataSet中数据表做过修改的所有行,并记录作了何种

14、修改(增、删、改)。 编写或生成相应的带参数的insert、delete或update语句。 对每个修改行,根据修改的种类,执行相应的更新数据库的语句。,1)标记修改行及修改种类,在dataSet中表的每一行对象有一个RowState属性,记录了该行是否作了修改及作了何种修改的信息: dataSet.Tablesstudents.Rows0.RowState 其值可为:DataRowState.Added/Modified/Deleted和Unchanged。 当dataSet中表数据载入后,各行的状态为Unchanged,当对表中某行进行修改后,会根据修改类型自动改变该行的状态。在调用Acc

15、eptChanges后,对应行状态恢复到Unchanged状态。 由于更新数据库的update方法是依据该状态来确定哪些行要修改和做什么修改,所以在用dataSet数据更新数据库前,不要调用用AcceptChanges。,2)编写或生成相应的带参数的SQL语句(1) 使用OleDBCommandBuilder产生更新数据库的带参数的SQL语句,OleDbCommandBuilder可根据oleDBDataAdapter中的Select Command中的select语句,即调用Fill方法时执行的select语句,生成带参数的update、delete或insert语句。 在窗口类中增加成员:

16、OleDbCommandBuilder oleDbCommandBuilder; 在LoadData加载(Fill)students数据语句后加: oleDbCommandBuilder = new OleDbCommandBuilder(oleDbDataAdapter); 实例化oleDbCommandBuilder,并把oleDbDataAdapter作为其属性DataAdapter值,在要生成SQL语句前, oleDbCommandBuilder必须能访问非空的oleDbDataAdapter.SelectCommand。 在生成SQL语句前,首先会执行上述的select语句,以获得对

17、应表的列名信息,为生成做准备。 生成的SQL语句将存放在该类的基类对应的三个private属性中:它们是UpdateCommand、DeleteCommand和InsertCommand。,生成SQL语句的条件(如UpdateCommand) 基类对应的属性为空(如UpdateCommand=null) dataSet对应数据表中存在对应状态的行(如存在Modified状态的行) 在下列调用中会调用oleDbCommandBuilder中生成SQL语句的程序(并非在初始化的时候): 调用其方法GetUpdateCommand或GetDeleteCommand或GetInsertCommand时

18、,返回对应的命令串。 调用其属性DataAdapter值对象oleDbDataAdapter所包含的方法:oleDbDataAdapter.Update(dataSet, “students”);该语句用生成的SQL语句及dataSet修改过的数据更新数据表。 比较特别是oleDbDataAdapter是oleDbCommandBuilder的DataAdapter属性值,其方法却要调用拥有它的对象方法以生成SQL语句,这种调用方法见“3)更新数据库”后的例。,生成带参数的SQL语句条件和时机:,加入生成SQL语句的语句:,在LoadData中实例化oleDbCommndBuilder后调用下

19、列语句以生成带参数的更新数据库的SQL语句。 oleDbCommandBuilder.GetDeleteCommand(); oleDbCommandBuilder.GetUpdateCommand(); oleDbCommandBuilder.GetInsertCommand(); 由于LoadData中先使用oleDbDataAdapter加载了students表,然后同样使用它加载classes表,所以如没有上述语句,则在update时,oleDbCommandBuilder. DataAdapter指向的oleDataAdapter的SelectCommand属性的CommandTex

20、t为Select * from classes,所以将生成对classes的更新语句。 而上述语句生成了关于students的SQL语句,在update时发现oleDbCommandBuilder中已存在这些语句,就不会再生成关于classes的更新语句。,OleDbCommandBuilder其他说明:,由上可知,SQL语句一但生成,改变oleDbDataAdapter的SelectCommand属性,由于生成SQL语句的第一个条件不满足,不会改变oldDbCommandBuilder中已生成的SQL语句。 oleDbCommandBuilder.RefreshSchema()可用于清空生成

21、的SQL语句(基类属性),可使生成SQL语句的第一个条件满足。 使用OleDbCommandBuilder的限制:select语句必须为单表的查询,包含主键,但不包含只读列(如计算列)。 为了生成 INSERT、UPDATE 或 DELETE 语句,OleDbCommandBuilder 会自动使用 SelectCommand 属性来检索所需的元数据集,以获得如列名等信息,所以会降低执行效率。,(2)编写更新数据库的SQL,如果Fill一个DataSet数据表对应的select语句牵涉多个表,就不能使用oleDbCommandBuilder生成更新数据库的SQL语句,必须手工编写。 目标:在F

22、orm的下方用DataGrid显示当前学生的各门课的名称及成绩,可以修改成绩但不能添加和删除,点击保存按钮后保存修改内容。 增加下列Form类成员: private DataRelation dataRelation; /students和grade的关联 private OleDbDataAdapter oleDbDataAdapter1;/用于grade表,把grade数据加载到DataSet,private void LoadGrade() oleDbDataAdapter1 = new OleDbDataAdapter(); oleDbDataAdapter1.SelectComman

23、d = new OleDbCommand(select a.id,a.subid,b.subname,a.grade from grade a,subjects b where a.subid=b.subid, oleDbConnection); oleDbDataAdapter1.Fill(dataSet, “grade”);/dataSet中产生grade表 /update时调用的update语句,其中“?”表示定位参数(非命名参数),依次和/下面oleDbDataAdapter1.UpdateCommand.Parameters中的参数对应。 oleDbDataAdapter1.Upda

24、teCommand = new OleDbCommand(update grade set grade=? where id=? and subid=?,oleDbConnection); /定义执行update时三个参数来自dataSet.grade表的那个列 /定义第一个参数:名为“grade”,对定位参数,参数按次序对应,名称无用 OleDbParameter gradeParameter = new OleDbParameter(grade, OleDbType.Integer); /该参数数据来源grade列 gradeParameter.SourceColumn = “grade”

25、; /数据取修改后数据,此语句可省略 gradeParameter.SourceVersion = DataRowVersion.Current;/缺省,/定义第二个参数id:数据取修改前数据 OleDbParameter idParameter = new OleDbParameter(id, OleDbType.Char,6); idParameter.SourceColumn = “id”; /数据来源于id列 idParameter.SourceVersion = DataRowVersion.Original; /定义第三个参数subid:数据取修改前数据,同时指定数据来源于subi

26、d列 OleDbParameter subidParameter = new OleDbParameter(subid, OleDbType.Char, 6,subid); subidParameter.SourceVersion = DataRowVersion.Original; /将三个参数依次加入参数表,作为update语句中的三个参数 oleDbDataAdapter1.UpdateCommand.Parameters.Add(gradeParameter); oleDbDataAdapter1.UpdateCommand.Parameters.Add(idParameter); o

27、leDbDataAdapter1.UpdateCommand.Parameters.Add(subidParameter); /建立名为students_grade的两表关系,联结条件students.id=grade.id dataRelation = new DataRelation(students_grade, dataSet.Tablesstudents.Columnsid, dataSet.Tablesgrade.Columnsid); /将关系加入dataSet.Relation中 dataSet.Relations.Add(dataRelation); 在LoadData方法最

28、后加LoadGrade(),设置并显示DataGrid:,private void SetDataGrid() DataGrid dataGrid = new DataGrid(); /dataGrid与Panel1对齐并设置大小相同 dataGrid.SetBounds(panel1.Location.X, panel1.Location.Y + panel1.Size.Height, panel1.Size.Width, panel1.Size.Height); /把dataGrid加入Form this.Controls.Add(dataGrid); dataGrid.CaptionTe

29、xt = “成绩”; dataGrid.DataSource = dataSet; /students_grade为LoadGrid中已建立的students和grade关系名,其/中students为父表,如此定义使dataGrid仅显示students的当前学生 /成绩,而非所有grade行。 dataGrid.DataMember = “students.students_grade”;,/定义两个在DataGrid中显示的列:课程名称和成绩 DataGridTextBoxColumn column1=new DataGridTextBoxColumn(); DataGridTextBo

30、xColumn column2=new DataGridTextBoxColumn(); column1.MappingName=subname; column1.HeaderText=课程名称; column2.MappingName=grade; column2.HeaderText=成绩; /把两个列加入dataGridTableStyle.GradeColumnStyles DataGridTableStyle dataGridTableStyle=new DataGridTableStyle(); dataGridTableStyle.GridColumnStyles.Add(col

31、umn1); dataGridTableStyle.GridColumnStyles.Add(column2); /若不设置下列属性,dataGrid将显示select所有列,上述设置不起作用 dataGridTableStyle.MappingName = grade; dataGrid.TableStyles.Add(dataGridTableStyle); 在Form的Load事件中加入:SetDataGrid(),3)更新数据库,使用下列语句更新数据库(保存按钮的click事件): /确保把和dataSet中students及grade绑定的控件数据写入dataSet this.Bin

32、dingContextdataSet,“students”.EndCurrentEdit(); this.BindingContextdataSet, grade.EndCurrentEdit(); oleDbDataAdapter.Update(dataSet, students); oleDbDataAdapter1.Update(dataSet,grade); Update执行流程如下: 如oleDbDataAdapter关联了一个oleDbCommandBuilder (即前者为后者的一个属性,判断方法如下例owner!=null) ,若后者尚未生成更新数据库的SQL语句(其基类对象相

33、应属性为空),则生成。 执行更新语句:若程序已设置oleDbDataAdapter中的属性如UpdateCommand中的update语句,则执行该语句(即由程序员编写数据库的更新语句),否则则执行oldDbCommandBuilder基类对象属性所存储的update语句 下页示例如何在一个对象(oleDbCommandBuilder)的属性值对象(oleDbDataAdapter)的方法中调用拥有它的对象( oleDbCommandBuilder )的方法(生成SQL的方法),例:commandBuilder对象的属性值对象dataAdapter的update方法调用commandBuild

34、er的方法GetSQL,public class DataAdapter public object owner; public string update() if (owner!=null) return (CommandBuilder)owner).GetSQL(); else return null; public class CommandBuilder private DataAdapter dataAdapter; private string UpdateText; public CommandBuilder(DataAdapter dataAdapter) this.data

35、Adapter = dataAdapter; this.dataAdapter.owner = this; public string GetSQL() UpdateText=update students set name=wangwhere id=01; return UpdateText; ,调用示例:若没有第二个语句,即dataAdapter不和commandBuilder关联,仍能调用update,但返回null。 DataAdapter dataAdapter = new DataAdapter(); CommandBuilder commandBuilder = new Comm

36、andBuilder(dataAdapter); MessageBox.Show(dataAdapter.update();,七)DataSet表的表达式列,目标:在窗口上动态显示该学生的平均成绩。 对DataSet中的students,增加计算列avggradec,其值为子表grade中grade字段值的平均值,并动态绑定到对应的TextBox。 private void AddAvgGradeToStudents() if (dataSet.Tablesstudents.Columnsavggradec = null) dataSet.Tablesstudents.Columns.Add(

37、avggradec); dataSet.Tablesstudents.Columnsavggradec.Expression =avg(child.grade); textBox3.DataBindings.Add(text, dataSet, students.avggradec); 在LoadData最后加AddAvgGradeToStudents() 设置textBox3为readonly。 修改成绩,平均成绩即刻更新。,DataColumn.Expresion,获取或设置表达式,用于筛选行、计算列中的值或创建聚合列,假设在grade表中已增加列c。 计算列: dataSet.Table

38、sgrade.Columns c.Expression= grade*0.9; 聚合列:支持sum、max、min和count等聚合函数,见上例。 为筛选器指定表达式:值为true/false。 dataSet.Tablesgrade.Columnsc.Expression= subid=sub001;,Expression中对父表或子表关系引用,通过在列名称前面加 Parent,就可以在表达式中引用父表。例如,Parent.Price 引用父表的名为 Price 的列。 通过在列名称前面加一个 Child,就可以在表达式中引用子表中的列。因为子关系可以返回多行,所以必须在聚合函数中包括对子列

39、的引用。例如,Sum(Child.Price) 将返回子表中名为 Price 的列的总和。 如果某个表有多个子表,则语法是:Child(RelationName)。例如,如果某个表有两个子表,它们的名称分别为 Customers 和 Orders,则 DataRelation对象被命名为 Customers2Orders,引用将为:Avg(Child(Customers2Orders).Quantity),八)使用Tag属性绑定列,目标:使用RadioButton选择性别,但Students.sex类型为bit,0表示男,1表示女。 需要在一个GroupBox中放两个RadioButton,其

40、Text分别为“男”和“女”,而实际只需要获得一个RadioButton的Checked状态就能确定性别。 由于值不同,所以不能使用RadioButton的Text属性和students.sex绑定,可用Tag属性与其绑定。这样的设置必须完成两部分工作: Tag值改变时(浏览时)要对RadioButton的状态作相应改变 RadioButton状态改变时要改变Tag值,RadioButton状态改变时改变Tag值,在RadioButton的CheckedChanged事件中实现: if (radioButton1.Checked) radioButton1.Tag = false; else

41、radioButton1.Tag = true; Students的sex属性类型为bit,其值只能取0和1,与radioButton1.Tag绑定后,Tag的值为true和false。,Tag值改变时要对RadioButton的状态作相应改变:,首先实现下列方法: private void SetSexRadioButton(object sender, EventArgs e) if (radioButton1.Tag.ToString() = ) radioButton1.Checked = false; radioButton2.Checked = false; return; if

42、(radioButton1.Tag.ToString() = False) radioButton1.Checked = true; radioButton2.Checked = false; else radioButton1.Checked = false; radioButton2.Checked = true; ,何时调用该方法:,方案一:在窗口打开后(Load事件)及按浏览按钮时,调用5次。 方案二:在窗口打开后(Load事件)和this.BindingContextdataSet, “students”对象的PositionChanged事件中调用,调用2次。 在BindingCo

43、ntrols最后加: radioButton1.DataBindings.Add(tag, dataSet, students.sex); this.BindingContextdataSet, students.PositionChanged += SetSexRadioButton; 在Form的Load事件中加: SetSexRadioButton(this, null);,九)使用程序对dataSet中数据表的插入、删除、修改和检索。,以上对dataSet的数据表的操作是通过绑定来实现的,修改控件中数据则自动更新数据表中数据,插入和删除则是通过this.BindingContextda

44、taSet, “students”的AddNew方法和RemoveAt方法实现。 直接对DataSet中数据表操作方法如下: 修改:dataSet.Tablesstudents.Rows0name = zhp; 插入:dataSet.Tablesstudents.Rows.InsertAt(DataRow row,int pos) 删除:dataSet.Tablesstudents.Rows.RemoveAt(int pos),检索:,DataSet中的Table提供了下列两种方法检索符合条件的行,返回符合条件的行。 Select方法: DataRow dataRow = dataSet.Ta

45、blesstudents.Select(id= + textBox4.Text + );/使用dataRow.GetLength(0)获得符合条件的行数 Find方法:检索主键值,必须先建立主键,见下例。 DataRow dataRow = dataSet.Tables“students”.Rows.Find(textBox1.Text);/找不到返回null 方法比较:Select检索条件任意,可返回多行,Find方法只能对建立的主键值检索,返回最多一行,由于表总关于主键排序,所以检索速度较select快很多。,检索实例:,目标:输入学生编号,按“检索”按钮后若该学生不存在,则提示,若存在,

46、则显示该学生信息: 分析:定位控件显示的行的唯一方法是设置Binding Context的Position属性,而Find和Select返回的是dataRow,余下的问题是如何由已知行dataRow获得该行在table中的行序号,.Net提供了该方法: dataSet.Tablesstudents.Rows.IndexOf(dataRow); 以下使对学生编号检索的程序:,private void button13_Click(object sender, EventArgs e) int idx; DataColumn dataColumn; dataColumn = new DataCol

47、umn1; dataColumn0 = dataSet.Tablesstudents.Columnsid; dataSet.Tables“students”.PrimaryKey = dataColumn; /至此为设置主键 DataRow dataRow=dataSet.Tablesstudents.Rows.Find(textBox4.Text); if (dataRow = null) MessageBox.Show(没有发现符合条件的行!); else idx=dataSet.Tablesstudents.Rows.IndexOf(dataRow); this.BindingConte

48、xtdataSet, students.Position = idx; ,1.2.2 可视化设计,构造DataSet:前面的设计方式,必须在程序运行后,才能确定DataSet的结构(包含哪些Table和Relation等),.Net可以使用XML文件构建DataSet类,这使程序设计和运行可不依赖于和数据库的连接,并且使数据库结构修改后,只要修改对应的XML文件,而不必修改程序。 类型化DataSet和非类型化DataSet:前者在程序设计时定义(可编写或生成)DataSet类的内部结构,编译时进行类型检查,所以类型安全,后者则在程序运行时产生DataSet对象的内部结构(1.2.1中例子的方

49、式),可能由于数据类型不一致而使运行时更容易发生错误。,设计步骤:,根据数据库中表结构生成DataSet1.XSD文件:使用菜单Add New Item/ DataSet进入可视化地构建DataSet模式(schema),可把Server Explorer中数据表拖入及使用工具栏中的Relation建立数据表之间的联系,然后保存(XML格式)。 依据上面生成的XSD文件产生DataSet类和对象定义:在Form中加入工具栏中DataSet,选择Typed dataset。Name选择examplea1. DataSet1(即对应上面XSD文件),系统根据XSD文件内容在dataSet11. D

50、esigner. cs文件中产生类定义DataSet1,并在Form1.Designer. cs中定义了该类的对象dataset11。 通过设置控件的DataBindings属性(可选dataset11数据项)实施绑定等设置,对应程序也在Form1.Desig ner. cs文件中生成。,两种类型DataSet数据的访问的区别:,非类型化DataSet(弱类型DataSet) dataSet.Tables“students”.Columns“id”或 dataSet.Tables0.Columns0 类型化DataSet(强类型DataSet) dataSet.students.idColum

51、n,1.2.3 报表设计:CrystalReport,基本原理: 使用报表设计器设计报表,设计内容存入特殊格式的CrystalReport.rpt文件中,该报表文件也可供其他语言(C+或VB)开发的程序使用。 同时生成了一个继承于ReportClass的报表类定义文件CrystalReport.cs,其中包含了该类与rpt文件的关联,用户通过该类实现对上述设计报表的操作。在该类定义文件中可以加入工具箱中的组件(把组件拖入CrystalReport.csDesigner页面)。 报表通过可视化控件CrystalReportViewer显示。用户只要实例化一个报表类对象,并把包含数据的DataSe

52、t对象传给它,由报表类完成对rpt文件的解析,获取数据并在CrystalReportViewer中显示报表。,报表的数据来源-用非类型化DataSet产生XSD,使用CrystalReport,在设计阶段必须确定报表的数据来源,即必须构建DataSet框架,报表设计时各数据项可选自构建好的DataSet。 在程序运行时,通过报表类的SetDataSource方法把实例化的DataSet(包含数据的)对象传递给报表,该DataSet必须包含报表设计时所用到数据项,或保证两者数据模型完全一致。 由于本例DataSet为非类型化,可使用下列语句把DataSet模型输出到XSD文件,供报表设计用: d

53、ataSet.WriteXmlSchema(dataset1.xsd);,一)设计List报表:学生基本信息表(CryStalReport1),构建报表数据源: 在项目中加入DataSet1.XSD:在Solution Explorer中右击项目名,选择Add/Existing Item,选择前面生成DataSet1.XSD文件。 系统会生成DataSet1.Designer.cs,其中定义了名为NewDataSet类,该类为依据XSD文件构造的类型化DataSet类,报表设计时可由此获得数据项 新建报表:选择菜单Project/Add New Item,选Reporting /Crystal

54、Report。 1)简要介绍Report Wizard: 选择Using the Report Wizard:以下是Wizard各步: 在Project Data/ADO.NET DataSets/examplea1. DataSet1中选择报表数据相关的表 维护表之间关系:对DataSet1中定义的表间关系进行删除,或根据列名(name)或主键自动建立表间关系。 选择报表中要输出的列:,选择分组信息: 选择统计信息: 分组排序: 报表中是否要包含图表 过滤条件 报表的风格:table含有表格线 2)从空白报表开始设计:选择As a Blank Report 出现一个空白报表,有5个部分组成,

55、分别是Report Header、Page Header、Details、Report Footer和Page Footer。 Report Header和Footer只出现在报表头一页和最后一页,Page Header和Footer出现在每一页上,Details为报表的主体-数据部分。 (1)加入要使用的数据项:右击报表,选择Field Explorer,在打开的窗口中右击DataBase Fields选择DataBase Expert,出现的对话框的Data页框中可选择Available Data Sources,其中列出了Project Data/ ADO.NET DataSets/ex

56、amplea1.NewDataSet中的所有数据表,把它们全部加入Selected Tables。在Link页框中,以图形方式显示了被选中表在NewDataSet所包含的表间关系,可增加通过classid列建立的Students和classes表的关联。,(2)设置Page Head:,在工具栏选择Text Object,放入Page Header。 右击该Text Object,选择Edit Text Object,输入“学生基本信息表” 右击该Text Object,选择Format Object,设置其字体和对齐方式 在Field Explorer中的Special Fields,选择P

57、rint Date,并把它拖到上述的标题下。,(3)设置Details,把Field Explorer中students的id、name、sex和Height和classes的name拖入Details中。 编辑Page Header中自动产生的Text Object,输入对应中文,使用Format Object设置对齐方式为居中。 右击报表,选择Preview Report,可预览报表,由于报表设计不需要连接数据库,所以数据为根据类型自动生成的模拟数据。 调整数据项位置、尺称、字体、对齐方式等 使用工具栏中的Box Object和Line Object为表格加上线框,线和框可跨越报表的不同区

58、域。,(4)使用Formula Field:性别输出,数据表中性别为bit类型,输出为True和fase,要求输出“男”,女。 在Field Explorer中右击Formula Fields,选New,输入Name为SexText,然后按“Use Expert”,进入Formula Editor。 通过选择Report Fields、Functions和Operators或输入 if(students.sex=true) then 女 else 男 在报表中删除Sex,然后加上SexText。,(5)分组统计:总平均身高和分组平均身高,插入总平均身高:右击报表,选择Insert/Summar

59、y,选择统计字段Height和统计函数average,统计字段自动被安排在Report Footer的Height列下。 班级分组平均身高: 在报表中插入分组块:右击报表,选择Insert/Group,选择依据哪个列值分组(选classes.classid)及对该列值排序方式(升/降),确认后报表上出现GroupHeaderSection1和Group FooterSection1,并在GroupHeaderSection1中出现字段Group #1 Name,删除它,为避免在每组开始时显示一个空行,右击该灰色条带选择Hide,则该块内容不输出。 在分组块中插入分组的平均身高:操作基本同插入总平均身高的操作,但Summary location选择Group #1。确认后统计字段被自动安排在GroupFootSection1中的Height列下。,分组修改:,右击GroupHeaderSe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论