版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、在ASP.NET 2.0中操作数据之六十四:GridView批量添加数据作者:heker2007 字体:增加 减小 类型:转载 时间:2016-05-18 我要评论前面介绍了批量更新,批量删除数据,这篇文章主要介绍如何实现批量添加数据,当然为了保证数据的完整性,我们在做这些批量操作的时候,都使用了事务来实现。导言:在前面的第62章GridView批量更新数据里,我们用GridView控件里定制了一个批编辑界面,同样的我们也可以定制一个批添加界面.假设有这种情况,我们接受一批从Tokyo(东京)发过来的货物:6种不同的tea 和 coffee,如果用户在一个DetailsVi
2、ew控件里一次输入一个产品,他将会重复的输入很多相同的值,比如相同的种类(Beverages),相同的供应商(Tokyo Traders),相同的discontinued值(False),以及相同的order值(0).重复性的输入这些相同的值不仅累,还很容易出错.只需额外多做一些工作,我们就可以创建一个批添加界面。用户只需一次行的选择supplier 和category,输入一系列产品的names 和unit prices,再点击一个按钮就可以将这些新产品添加进数据库(如图1所示).这些添加的产品的ProductName 和UnitPrice数据由界面上方的2个DropDownList控件指定
3、,Discontinued 和UnitsOnOrder的值由“硬编辑”指定,分别为false和0.图1:批添加界面本教程,我们将创建一个如图1所示的批添加界面。在前面2章的基础上我们将把添加过程用事务封装以保证原子操作.让我们开始吧!第一步:创建一个展示界面我们将创建一个包含2个区域的单一页面:展示区域和添加区域.我们在这一步创建的是展示区域,它包含一个用于展示产品的GridView控件以及一个标题为“Process Product Shipment”的button按钮.当点击该按钮时,展示界面将替换为一个如图1所示的添加界面.如果点“Add Products from Shipment” 或
4、 “Cancel”按钮时又会返回展示页面.添加界面将在第二步完成.这个包含2个界面的页面每次只能让一个界面可见。我们将用2个Panel Web控件作为容器包含这2个界面一个Panel Web控件包含一个界面.首先打开BatchData文件夹里的BatchInsert.aspx页面,在设计器模式里从工具箱里拖一个Panel控件到页面(如图2所示),设置其ID为DisplayInterface.当将Panel控件拖到页面时其Height 和 Width属性分别为50px 和 125px.在属性窗口里清除这些属性.图2:从工具箱里拖一个Panel控件到页面然后拖一个Button 和 GridView
5、控件到Panel控件里。设Button的ID为ProcessShipment ,Text属性为“Process Product Shipment”. 设GridView的ID为ProductsGrid,从其智能标签里将其绑定到一个名为ProductsDataSource的ObjectDataSource.设置该ObjectDataSource调用ProductsBLL class类的GetProducts方法.由于该GridView控件只用来展示数据,从UPDATE, INSERT, DELETE标签里选“(None)”. 点Finish完成设置图3:调用ProductsBLL C
6、lass类的GetProducts方法来显示数据图4:在UPDATE, INSERT, DELETE标签里选“(None)”完成ObjectDataSource设置后,Visual Studio会自动地添加一些BoundFields以及一个CheckBoxField。只保留ProductName, CategoryName, SupplierName, UnitPrice, 以及Discontinued这几列.你可以再做一些外观的改进.我将UnitPrice列定制为货币值,重新对列进行了排序,再对一些列的HeaderText值进行了修改.再在GridView的智能标签里启用了“分页”和“排序”
7、功能.完成上述工作后,页面的声明代码看起来应该和下面的差不多:?12345678910111213141516171819202122232425262728293031<asp:Panel ID="DisplayInterface" runat="server"> <p> <asp:Button ID="ProcessShipment" runat="server" Text="Process Product Shipment&qu
8、ot; /> </p> <asp:GridView ID="ProductsGrid" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ProductsDataSource"> <
9、Columns> <asp:BoundField DataField="ProductName" HeaderText="Product" SortExpression="ProductName" /> <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True" Sor
10、tExpression="CategoryName" /> <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True" SortExpression="SupplierName" /> <asp:BoundField DataField="UnitPrice" DataFormatStrin
11、g="0:c" HeaderText="Price" HtmlEncode="False" SortExpression="UnitPrice"> <ItemStyle HorizontalAlign="Right" /> </asp:BoundField> <asp:CheckBoxField DataField="Discontinued
12、" HeaderText="Discontinued" SortExpression="Discontinued"> <ItemStyle HorizontalAlign="Center" /> </asp:CheckBoxField> </Columns> </asp:GridView> <asp:ObjectDataSource ID="ProductsDa
13、taSource" runat="server" OldValuesParameterFormatString="original_0" SelectMethod="GetProducts" TypeName="ProductsBLL"> </asp:ObjectDataSource></asp:Panel>我们注意到Button 和 GridView控件的声明代码出现在<asp:Panel>标签内部,因为这些控件置于名为Displa
14、yInterface的Panel控件里面,我们可以将Panel控件的Visible 属性设置为false来隐藏这些控件.我们将在第三步看到,当点击一个按钮时,通过编程的方式改变Panel控件的Visible属性以显示添加界面.花点时间在浏览器里登录该页面.如图5所示,你将看到一个显示为“Process Product Shipment”的button按钮,其下的GridView控件每次列出10个产品.图5:GridView列出了产品并启用排序和分页功能第二步:创建添加界面创建完展示界面后,我们将创建添加界面。在本教程,我们的添加界面允许用户同时添加5个产品,且这5个产品的category 和
15、supplier是一样的,而names 和 nit price值不同.在ID为DisplayInterface的Panel控件下面,从工具箱里拖一个Panel控件到页面,设置其ID为InsertingInterface,Visible属性为false,并清除其Height 和 Width属性值。我们将在第三步添加代码将其Visible属性改为true.接下来我们将创建如图1所示的添加界面。该界面本来可以通过一些HTML技术来创建的,不过在这里我们将使用一个很简单的4列7行的table表.注意:虽然在设计器模式里可以使用工具箱的工具来添加<table> elements元素,不过那样
16、会自动添加一些我们不需要的style属性设置.因此,我更偏向于在源视图模式里添加HTML <table> elements元素. 当写好类<table>声明代码后,我喜欢立即切换到设计器模式,再添加Web控件并设置其属性。当心中有数,已经想好了要创建几行几列的时候,我倾向于使用静态HTML(static HTML)而不是Table Web控件,原因是如果使用Table Web控件的话,我们必须通过FindControl("controlID")的方式来访问放置在里面的的Web控件.不过话又说回来,如果是要创建一个动态变化的表(dynamically-
17、sized tables)的话比如该表的行和列都绑定到数据库或者基于用户自定义的标准格式,我还是要使用Table Web控件,原因很简单,我们可以通过编程来创建该Table Web控件.在ID为InsertingInterface的Panel控件的<asp:Panel>标签里输入如下的声明代码:?123456789101112131415161718192021222324252627282930313233343536373839404142<table class="DataWebControlStyle" cellspacing="0&qu
18、ot;> <tr class="BatchInsertHeaderRow"> <td class="BatchInsertLabel">Supplier:</td> <td></td> <td class="BatchInsertLabel">Category:</td> <td></td> </tr> <tr class="
19、BatchInsertRow"> <td class="BatchInsertLabel">Product:</td> <td></td> <td class="BatchInsertLabel">Price:</td> <td></td> </tr> <tr class="BatchInsertAlternatingRow"> &
20、lt;td class="BatchInsertLabel">Product:</td> <td></td> <td class="BatchInsertLabel">Price:</td> <td></td> </tr> <tr class="BatchInsertRow"> <td class="BatchInsertLabel"&g
21、t;Product:</td> <td></td> <td class="BatchInsertLabel">Price:</td> <td></td> </tr> <tr class="BatchInsertAlternatingRow"> <td class="BatchInsertLabel">Product:</td> <
22、td></td> <td class="BatchInsertLabel">Price:</td> <td></td> </tr> <tr class="BatchInsertRow"> <td class="BatchInsertLabel">Product:</td> <td></td> <td class="
23、BatchInsertLabel">Price:</td> <td></td> </tr> <tr class="BatchInsertFooterRow"> <td colspan="4"> </td> </tr></table>该<table>声明代码里暂时还未包含任何的Web控件。我们注意到每一个<tr> element元素都有明确的CSS c
24、lass设置:放置名为supplier 和category的DropDownLists控件的“头顶行”对应的是BatchInsertHeaderRow;放置“Add Products from Shipment” 和“Cancel”按钮的“底部行”对应的是BatchInsertFooterRow;那些包含product和unit price的TextBox控件的行交替的运用BatchInsertRow和BatchInsertAlternatingRow.我已经在Styles.css文件里创建里相应的CSS classes,代码如下:?123456789101112131415161718192
25、02122232425262728/* Styles for /BatchData/BatchInsert.aspx tutorial */.BatchInsertLabel font-weight: bold; text-align: right; .BatchInsertHeaderRow td color: White; background-color: #900; padding: 11px; .BatchInsertFooterRow td text-align: center; paddin
26、g-top: 5px; .BatchInsertRow .BatchInsertAlternatingRow background-color: #fcc;输入这些代码后,切换到设计视图,该<table>看起来是一个4列7行的表,如图6所示:图6:添加界面为一个4列7行的表现在我们在添加界面里添加Web控件.从工具箱拖2个DropDownList到表的相应方格里一个用来显示supplier另一个用来显示category.将用来显示supplier的那个DropDownList的ID设为Suppliers,并将其绑定到一个名为SuppliersDataS
27、ource的ObjectDataSource.设置该ObjectDataSource调用SuppliersBLL class类的GetSuppliers方法.并在UPDATE标签里选“(None)”,点击Finish完成设置向导.图7:设置ObjectDataSource调用SuppliersBLL Class类的GetSuppliers方法设置该DropDownList显示CompanyName列,而传递的值为SupplierID列.图8:显示CompanyName列,传递的是SupplierID列的值将第2个DropDownList的ID设为Categories,并将其绑定到一个名为Cat
28、egoriesDataSource的ObjectDataSource.该ObjectDataSource调用CategoriesBLL class类的GetCategories方法. 在UPDATE标签里选“(None)”,再点Finish完成设置. 最后设置该DropDownList控件显示CategoryName列,传递CategoryID列的值.当添加这2个DropDownList控件并绑定到相应的ObjectDataSources后,你的屏幕看起来应该和图9差不多:图9:“头部行”包含显示Suppliers和Categories的DropDownList控件我们现在需要创建收集每个产品
29、的name和price信息的TextBox控件。在下面的每行对应的name和price方格里各拖放一个TextBox控件. 分别设置它们的ID为ProductName1, UnitPrice1,ProductName2, UnitPrice2,依次类推.对每个price TextBoxes添加一个CompareValidator控件,设置其ControlToValidate属性为相应控件的ID值.同时将Operator属性设置为GreaterThanEqual,ValueToCompare 属性设置为“0”, Type属性设置为Currency.这样一来可以保证输入的价格为有效的大于或等于0的
30、货币值.同时将Text属性设置为“*”;ErrorMessage属性为“The price must be greater than or equal to zero. Also, please omit any currency symbols.”。注意:我们并没有在添加界面里包含任何的RequiredFieldValidator控件,即便是数据库表Products的ProductName不允许为NULL值.举个例子,如果用户只想在前3行输入产品的name和unit price,而最后2行为空,我们就仅仅向数据库添加了3个产品。由于ProductName是必需的,当输入了name值后,我们只
31、需要通过编程检查用户是否输入了该产品的unit price值.我们将在第四步进行该检查.当用户输入了数据,但如果输入值包含货币符号的话,CompareValidator控件将报告无效数据.在每个unit price TextBoxe控件前添加一个“$”符合,提示用户输入数据的时候忽略货币符号.最后,在InsertingInterface Panel控件里添加一个ValidationSummary控件,设置其ShowMessageBox属性为true,ShowSummary属性为false.有了这些设置后,当用户输入一个无效的unit price值后,在TextBox控件旁边将会出现一个星号,且
32、ValidationSummary控件将显示一个客户端的消息框,显示相应的错误消息.此时,你的屏幕看起来和图10差不多.图10:添加界面现在包含显示产品的Names和Prices的TextBox控件接下来我们要在底部行添加“Add Products from Shipment” 和 “Cancel”按钮.从工具箱拖2个Button控件到界面的底部,分别设置其ID为AddProducts和CancelButton;同时分别设其Text属性为“Add Products from Shipment”和“Cancel”.此外,将 CancelButton按钮的CausesValidation属性设置为
33、false.最后,我们需要添加一个Label Web控件来显示有关这2个界面的状态信息.比如:当用户成功地添加了一批产品时我们希望切换到展示界面并显示确认消息.当然,如果用户输入产品信息时只提供了price而没有提供name信息,我们就需要显示一个警告信息,提示用户ProductName是必需的.由于我们需要显示与这2个界面有关的信息,将该控件放在这2个Panel控件的上方.从工具箱里拖一个Label Web控件到页面顶部,设其ID为StatusLabel,清除其Text属性,设其Visible属性和EnableViewState属性为false. 我们在以前的教程里探讨过,将EnableVi
34、ewState属性设为false的话,我们可以通过编程的方式改变Label控件的属性值,而当发生页面回传时其又回到默认状态.当发生某些用户行为(user action)时,会显示状态信息,而当页面回传时,状态信息又消失了.最后设置StatusLabel的CssClass属性为“Warning”,这是我们在Styles.css文件里定义的CSS class名称.下图显示的是添加并设置Label控件后的样子图11:在Panel控件上面放置id为StatusLabel的Label控件第三步:在展示界面和添加界面之间切换到此,我们已经完成了展示和添加界面,不过我们仍然有2个任务要做:1.在展示界面和添
35、加界面之间切换2.将产品添加到数据库当前,展示界面是可见的而添加界面是隐藏的.这是因为DisplayInterface Panel控件的Visible属性为true(默认值), 而InsertingInterface Panel控件的Visible属性为false.当点击“Process Product Shipment”按钮时,我们向从展示界面切换到添加界面。为此,创建该按钮的Click事件处理器,包含以下代码:?12345protected void ProcessShipment_Click(object sender, EventArgs e) DisplayInterfac
36、e.Visible = false; InsertingInterface.Visible = true;该代码仅仅隐藏DisplayInterface Panel而显示InsertingInterface Panel.接下来,我们为添加界面里的“Add Products from Shipment”和“Cancel” 按钮创建事件处理器.当任何一个按钮点击时,我们需要切换到展示界面.创建这2个按钮的Click事件处理器以调用ReturnToDisplayInterface方法我们马上就要创建该方法.该方法除了隐藏InsertingInterface Panel并显示DisplayI
37、nterface Panel外,还需要将Web控件返回到其预编辑状态(pre-editing state).即把DropDownList控件的属性SelectedIndex设置为0,清除TextBox控件的Text属性.注意:仔细思考一下,如果在返回展示界面以前,我们没有将这些控件返回到预编辑状态的话将会发生什么事情呢?比如用户点击“Process Products from Shipment”按钮,然后输入产品信息,再点“Add Products from Shipment”按钮,这样将添加产品并返回展示页面。如果用户又想添加另一批产品,一旦点击“Process Product Shipme
38、nt”按钮时将切换到添加界面,但是DropDownList控件的值和TextBox控件的值依然是以前的值.?12345678910111213141516171819202122232425262728293031323334protected void AddProducts_Click(object sender, EventArgs e) / TODO: Save the products / Revert to the display interface ReturnToDisplayInterface(); protected vo
39、id CancelButton_Click(object sender, EventArgs e) / Revert to the display interface ReturnToDisplayInterface(); const int firstControlID = 1;const int lastControlID = 5; private void ReturnToDisplayInterface() / Reset the control values in the inserting interface Suppli
40、ers.SelectedIndex = 0; Categories.SelectedIndex = 0; for (int i = firstControlID; i <= lastControlID; i+) (TextBox)InsertingInterface.FindControl("ProductName" + i.ToString().Text = string.Empty; (TextBox)InsertingInterface.FindControl("Un
41、itPrice" + i.ToString().Text = string.Empty; DisplayInterface.Visible = true; InsertingInterface.Visible = false;上述2个Click事件处理器都仅仅简单的调用ReturnToDisplayInterface方法,不过我们将在第四步完善“Add Products from Shipment”的Click事件,添加代码以保存产品.ReturnToDisplayInterface方法一开始就把Suppliers和C
42、ategories的DropDownList控件返回其第一项;常量firstControlID和lastControlID分别用来设置添加界面里的标明产品名称和单价的TextBoxe控件的开始和结束索引值. 在一个for循环里设置这些控件的Text属性为空字符串.最后重新设置Panels控件的Visible属性,以显示展示界面而隐藏添加界面.花点时间在浏览器里测试该页面,当首次登录时你将看到如图5所示的画面,点“Process Product Shipment”按钮,页面将回传并切换到如图12所示的添加界面,不管点“Add Products from Shipment”还是“Cancel”按钮
43、都将返回展示界面.注意:当浏览添加界面时,测试一下与unit price TextBox对应的验证控件。如果你输入的不是货币值或价格比0小,当点击“Add Products from Shipment”按钮时,就会弹出一个客户端的警告消息.图12:点击Process Product Shipment” 按钮后,将切换到添加界面.第四步:添加产品剩下要做的事情是在“Add Products from Shipment”按钮的Click事件处理器里将产品添加到数据库.为此,我们可以创建一个ProductsDataTable,并为要插入的产品添加一个ProductsRow instance实例。一旦
44、添加完ProductsRows后,我们就调用并把ProductsDataTable传递给ProductsBLL class类的UpdateWithTransaction方法.记得我们是在第61章在事务里对数据库修改进行封装里创建的UpdateWithTransaction方法,该方法将ProductsDataTable传递给ProductsTableAdapter的UpdateWithTransaction方法.于是启动一个ADO.NET事务,TableAdatper针对添加的每一个ProductsRow向数据库发出一个INSERT命令.如果所有的添加无误则提交事务,否则对事务回滚.对“Add
45、 Products from Shipment”按钮的Click处理器进行编码时,应该执行一些误差校验,因为我们没有在添加界面里使用RequiredFieldValidators控件,某个用户可能输入了产品的price而忽视里其name。由于产品的name是必须的,如果出现这种情况的话,我们需要提醒用户并中断inserts操作.完整的代码如下:?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676
46、86970717273747576protected void AddProducts_Click(object sender, EventArgs e) / Make sure that the UnitPrice CompareValidators report valid data. if (!Page.IsValid) return; / Add new ProductsRows to a ProductsDataTable. Northwind.ProductsDataTable products = new Northw
47、ind.ProductsDataTable(); for (int i = firstControlID; i <= lastControlID; i+) / Read in the values for the product name and unit price string productName = (TextBox)InsertingInterface.FindControl ("ProductName" + i.ToString().Text.Trim(); string unit
48、Price = (TextBox)InsertingInterface.FindControl ("UnitPrice" + i.ToString().Text.Trim(); / Ensure that if unitPrice has a value, so does productName if (unitPrice.Length > 0 && productName.Length = 0) / Display a warning and exit this
49、event handler StatusLabel.Text = "If you provide a unit price you must also " + "include the name of the product." StatusLabel.Visible = true; return; / Only add the product if a product name value is provided if (
50、productName.Length > 0) / Add a new ProductsRow to the ProductsDataTable Northwind.ProductsRow newProduct = products.NewProductsRow(); / Assign the values from the web page newProduct.ProductName = productName; newProduct.Supplier
51、ID = Convert.ToInt32(Suppliers.SelectedValue); newProduct.CategoryID = Convert.ToInt32(Categories.SelectedValue); if (unitPrice.Length > 0) newProduct.UnitPrice = Convert.ToDecimal(unitPrice); / Add any "default" values newPro
52、duct.Discontinued = false; newProduct.UnitsOnOrder = 0; products.AddProductsRow(newProduct); / If we reach here, see if there were any products added if (products.Count > 0) / Add the new products to the database using a transacti
53、on ProductsBLL productsAPI = new ProductsBLL(); productsAPI.UpdateWithTransaction(products); / Rebind the data to the grid so that the producst just added are displayed ProductsGrid.DataBind(); / Display a confirmation (don't use the Warning CSS class, though
54、) StatusLabel.CssClass = string.Empty; StatusLabel.Text = string.Format( "0 products from supplier 1 have been added and filed under " + "category 2.", products.Count, Suppliers.SelectedItem.Text, Categories.SelectedItem.Text); Stat
55、usLabel.Visible = true; / Revert to the display interface ReturnToDisplayInterface(); else / No products supplied! StatusLabel.Text = "No products were added. Please enter the product " + "names and unit prices in the textboxes.&qu
56、ot; StatusLabel.Visible = true; 该事件处理器开始时检查Page.IsValid属性返回的值是否为true。如果返回的为false,那就意味着至少有一个CompareValidators控件发现了无效的数据.此时,我们要么停止添加产品;要么将用户键入的unit price值向ProductsRow的UnitPrice属性赋值时,以抛出一个异常告终.接下来创建一个新的ProductsDataTable instance实例(也就是products),在一个for循环里遍历有关name和unit price的TextBox控件,并将其Text属性读取
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 门面出租合同书
- 2026肾脏保养养生课件
- 2026田园养生知识课件
- 2026智慧中医知识课件
- 反不正当竞争规范自我承诺函(7篇)
- 市场营销数据分析与预测指南
- 互联网企业IT运维人员服务器故障排查流程手册
- 食堂会计工作制度及流程
- 餐厅小时工日常工作制度
- 饲料厂12小时工作制度
- 2026年教案合集2026年春人教版八年级下册英语Unit 1~Unit 8全册教案新版
- 金融职务犯罪及几种常见罪名课件
- 维修改造加固工程监理质量评估报告
- 2023甘肃庆阳市检察机关决定招聘聘用制书记员15人笔试备考题库及答案解析
- 农业机械化生产学(已讲修改版)
- DB37T 3314-2018肥料中海藻酸含量测定 分光光度法
- GB/T 3994-2005粘土质隔热耐火砖
- 新闻写作(新闻与写作)
- STEMI心电图的诊断(ST段抬高性心肌梗死的诊断)课件
- 马工程西方经济学(第二版)教学课件-1
- 《兰亭序》中楷毛笔临摹字帖可打印
评论
0/150
提交评论