




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、在ASP.NET 2.0中操作数据之十七:研究插入、更新和删除的关联事件作者:heker2007 字体:增加 减小 类型:转载 时间:2016-05-07 我要评论本文主要讲解ASP.NET 2.0中如何在点击插入、更新、删除等按钮时关联和触发事件,以便我们在事件中写代码,实现我们期望的效果。导言当使用GridView、DetailsView或FormView控件的内建插入、编辑或删除特征时,在用户添加一条新记录或更新/删除一条现在记录的过程中发生了多个步骤。正如我们之前一节里所讨论的,在GridView中编辑一行时,保存(Update)和取消(Cancel)按钮将取代编辑
2、(Edit)按钮,并且绑定列转换成TextBox。在用户更新了数据并点击保存按钮之后,下述步骤在回传时执行:1.该GridView控件根据当前编辑行的唯一标识字段(通过DataKeyNames属性)组装它的ObjectDataSource的UpdateParameters参数,连同用户输入的值2.该GridView控件调用它的ObjectDataSource的Update()方法,它转而调用潜在对象的适当的方法(ProductsDAL.UpdateProduct,我们之前一节里)3.现在,这些隐含的数据,包含保存后的更改,被重新绑定到GridView控件在这一连串的步骤里,触发了许多事件,这让
3、我们可以创建事件处理程序从而在需要的地方增加自定义逻辑。例如,在第1步之前,触发GridView的事件。在这里,如果有什么validation错误我们可以取消更新请求。当调用Update()方法时,触发ObjectDataSource的Updating事件,提供了增加或自定义UpdateParameters的值的机会。在ObjectDataSource的潜在对象的方法完全执行后,触发ObjectDataSource的Updated事件。针对Updated事件的事件处理程序可以检查更新操作的相关详细信息,例如影响了多少行数据,或者是否引发了一个异常。最后,在第2步之后,GridView的RowU
4、pdated事件触发;针对此事件的事件处理程序可以检查关于刚刚完成的更新操作的相关额外信息。图1描述了使用GridView更新时这一系列连续的事件和步骤。图1里的这个事件模式不仅是在GridView的更新操作。从GridView、DetailsView或者FormView里插入、更新或者删除数据时,数据Web服务器控件和ObjectDataSource都会发生这一连串的pre-level和post-level的事件。图1: 当在GridView里更新数据时,触发一连串的Pre-和Post-事件在这一节里,我们将探讨使用这些事件从而扩展ASP.NET数据Web服务器控件的内建插入、更新和删除功能
5、。我们也会看看如何自定义编辑界面从而仅仅更新部分产品字段。第一步: 更新产品的ProductName和UnitPrice字段在之前一节的编辑界面里,包含了产品的所有字段并且它们都不是只读的。如果我们从GridView中剔除一列(QuantityPerUnit),那么当更新时数据Web服务器控件就不会设置ObjectDataSource的QuantityPerUnit UpdateParameters的值。ObjectDataSource则传入一个null值到UpdateProduct这个业务逻辑层的方法,它将当前编辑的数据库记录的QuantityPerUnit字段更改为值。同样地,如果是一个必
6、需的字段,例如ProductName,如果从编辑界面中剔除了,那么此更新将会失败并抛出一个“Column 'ProductName' does not allow nulls”异常。导致这一现象的原因是ObjectDataSource被配置为调用ProductsBLL类的UpdateProduct方法,它预期每一个产品字段都对应一个输入参数。因此,ObjectDataSource的UpdateParameters集合包含了该方法的每一个输入参数。如果我们希望提供一个允许最终用户仅仅可以更新部分字段的数据Web服务器控件,那么我们需要在ObjectDataSource的Updat
7、ing事件处理程序中编程设置缺失的UpdateParameters值,或者创建并调用一个预期部分字段的BLL方法。让我们在接下来的步骤中探讨。特别地,让我们创建一个在一个可编辑的GridView中仅显示ProductName和UnitPrice字段的页面。这个GridView的编辑界面将仅仅允许用户更新两个显示的字段,ProductName和UnitPrice 。因为这个编辑界面仅仅提供产品的部分字段,我们需要创建一个ObjectDataSource,它使用现有的BLL的UpdateProduct方法并在Updating事件处理程序中编程设置产品的缺少的字段的值,或者我们需要创建一个新的BLL
8、方法,它仅接受那些在GridView中已经定义的部分字段。在这一节里,我们使用后者,创建一个UpdateProduct方法的重载,它提取3个输入参数:productName、unitPrice和productID:?123456789101112131415161718192021System.ComponentModel.DataObjectMethodAttribute (System.ComponentModel.DataObjectMethodType.Update, false)public bool UpdateProduct(string productNa
9、me, decimal? unitPrice, int productID) Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID); if (products.Count = 0) / no matching record found, return false return false; Northwind.Produc
10、tsRow product = products0; product.ProductName = productName; if (unitPrice = null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value; / Update the product record int rowsAffected = Adapter.Update(product);
11、160; / Return true if precisely one row was updated, otherwise false return rowsAffected = 1;跟原有的UpdateProduct方法类似,这个重载方法首先检查是否在数据库中存在一个指定ProductID的产品。如果不存在,它返回false,指示更新产品信息的请求失败。否则,它因而更新现存的产品记录的ProductName和UnitPrice字段并通过调用TableAdapter的Update()方法提交此更新,传入ProductsRow实例。通过这些对我们的P
12、roductsBLL类的额外处理,我们现在可以创建一个简单GridView界面。打开EditInsertDelete文件夹中的DataModificationEvents.aspx ,添加一个GridView控件到页面。新建一个ObjectDataSource并配置它使用ProductsBLL类,它的Select()方法映射到GetProducts ,Update()方法映射到仅接受productName、unitPrice和productID输入参数的UpdateProduct方法重载。图2展示了映射ObjectDataSource的Update()方法到ProductsBLL类的新的Upd
13、ateProduct方法重载时的数据源配置向导。图 2: 映射ObjectDataSource的Update()方法到新的UpdateProduct重载因为我们的例子将仅仅需要编辑数据的能力,不需要插入或删除记录,那么花些时间明确地指明该ObjectDataSource的Insert()和Delete()方法不会映射到ProductsBLL类的任何方法-通过到INSERT和DELETE的tab页并从下拉列表中选择(无)。图 3: 在INSERT和DELETE的Tab页,从下拉列表中选择(无)完成了此向导后,从GridView的职能标记里勾选上启用编辑。完成了此数据源配置向导并绑定到GridVi
14、ew后,Visual Staudio就已经添加好它们的声明语法。到源视图察看该ObjectDataSource的声明标记,它将如下所示:?123456789101112131415161718192021System.ComponentModel.DataObjectMethodAttribute (System.ComponentModel.DataObjectMethodType.Update, false)public bool UpdateProduct(string productName, decimal? unitPrice, int productID)&
15、#160; Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID); if (products.Count = 0) / no matching record found, return false return false; Northwind.ProductsRow product = products0; &
16、#160;product.ProductName = productName; if (unitPrice = null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value; / Update the product record int rowsAffected = Adapter.Update(product); / Return true if precis
17、ely one row was updated, otherwise false return rowsAffected = 1;因为ObjectDataSource的Insert()和Delete()方法没有映射,也就没有InsertParameters或者DeleteParameters片段。此外,因为方法映射到UpdateProduct方法重载,它仅接受3个输入参数,UpdateParameters片段也就仅包含3个Parameter实例。注意到ObjectDataSource的属性被设置为original_0。这个属性是使用数据源配置向导时Visual Studi
18、o自动设置的。因此,由于我们的BLL方法不需要传入原始的ProductID值,从ObjectDataSource的声明语法中删除所有这些属性设置。注意: If you如果你只是简单地在设计视图里从属性窗口清除OldValuesParameterFormatString属性的值,这个属性会依旧存在于声明语法里,但会被设置为一个空字符串。要么从声明语法里把该属性通通删掉,要么从属性窗口,设置它的值为默认值:0 。虽然ObjectDataSource仅仅包含对productName、unitPrice和productID的UpdateParameters,Visual Studio还是为产品的每一个
19、字段添加一个绑定列或CheckBoxField。图 4: 对应产品的每一个字段,GridView都包含一个BoundField或CheckBoxField当最终用户编辑一个产品并点击它的保存按钮(Update),该GridView遍历那些可编辑的字段,然后把用户输入的值赋值到ObjectDataSource的UpdateParameters集合里对应的参数。如果没有对应的参数,GridView则添加一个到参数集合里。因此,如果我们的GridView包含对应产品的所有字段的绑定列或CheckBox列,那么ObjectDataSource则会调用能接受这些参数的方法重载,而不顾ObjectData
20、Source的声明标记指定只接受3个输入参数的事实(见图5)。类似地,如果存在某些由GridView非只读列构成的组合,而没有一个UpdateProduct重载能接受相应的参数,则会在试图保存时引发一个异常。图 5: GridView将添加参数到ObjectDataSource的UpdateParameters集合为了确保ObjectDataSource调用仅接受productName、unitPrice和productID参数的UpdateProduct重载,我们需要限定GridView仅包含ProductName和UnitPrice这两个可编辑的列。这可以通过删除其他绑定列和CheckBo
21、x列,或者把这些列的ReadOnly属性设置为true实现,又或者上述两种方法结合使用。在本节里让我们简单地删除除了ProductName和UnitPrice绑定列以外的GridView的所有列,然后,GridView的声明标记将如下所示:?12345678910<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID=&quo
22、t;ObjectDataSource1"> <Columns> <asp:CommandField ShowEditButton="True" /> <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="
23、ProductName" /> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> </Columns></asp:GridView>即使重载预期3个输入参数,在我们的GridView里仅包含两个绑定列。这是因为productID输
24、入参数是一个主键(primary key)的值,它通过当前编辑行的DataKeyNames属性传入值。我们的GridView控件,连同这个UpdateProduct重载,允许一个用户仅仅编辑产品的名称和单价而不会丢失产品的其他字段。图 6: 仅允许编辑 ProductName和UnitPrice的界面完善UnitPrice格式化虽然图6所示的GridView实例能够正常工作,UnitPrice字段还完全未被格式化,导致显示价格时缺少货币符号,还有4个小数位。为了在非编辑状态的行应用货币格式,只需要简单地设置UnitPrice绑定列的DataFormatString属性为0:c,还有它的Html
25、Encode属性为false 。图 7: 设置UnitPrice绑定列的DataFormatString和HtmlEncode属性通过此项更改,处于非编辑状态的行将价格格式化为货币;然而,当前编辑的行,仍然显示为没有货币符号并保留四位小数。图 8: 现在,非编辑状态的行格式化为货币值通过设置此绑定列的ApplyFormatInEditMode属性为true(默认为false),可以把DataFormatString属性里指定的格式化指令应用到编辑界面。图 9: 设置此绑定列的ApplyFormatInEditMode属性为true通过这个更改,当前编辑行里显示的UnitPrice值也被格式化为
26、货币。图 10: 现在,当前编辑行的值也被格式化为货币然而,如果把产品价格更新为文本框里带货币符号的值 例如$19.00 则会抛出一个FormatException异常。当GridView尝试把用户提供的值赋值到ObjectDataSource的UpdateParameters集合,它无法把UnitPrice字符串“$19.00”转换成参数要求的decimal类型(见图11)。为了补救这个问题我们可以为GridView的RowUpdating事件添加一个事件处理程序并让它把用户输入的UnitPrice格式化为货币格式的decimal 。这个GridView的RowUpdating事件接受的第二
27、个参数是一个GridViewUpdateEventArgs类型的对象,它包含一个NewValues字典,当中的每一个属性保存着用户输入的值,准备赋值到ObjectDataSource的UpdateParameters集合。我们可以重写现有的NewValues集合中的UnitPrice值为一个货币金额,通过下面的事件处理程序中的代码进行解析:?1234567protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e) if (e.NewValues"UnitPrice"
28、!= null) e.NewValues"UnitPrice" = decimal.Parse(e.NewValues"UnitPrice".ToString(), System.Globalization.NumberStyles.Currency);如果用户提供了一个诸如“$19.00”的UnitPrice值,这个值会被通过Decimal.Parse计算并解析为货币金额的值重写。这将正确的解析货币值,无论是货币符号
29、、逗号、小数点、等等,并使用System.Globalization命名空间的NumberStyles枚举。图11展示因用户输入的UnitPrice值带有货币符号引起的问题,还展示了如果利用GridView的RowUpdating事件处理程序从而正确地解析这样的输入。图 11: 现在,当前编辑行的UnitPrice值被格式化为货币金额第二步: 阻止NULL UnitPrices虽然数据库被配置为允许Products表里的UnitPrice字段为NULL值,但我们可能希望防止用户访问这个特别的页面并指定一个空的UnitPrice值。更确切地说,如果用户在编辑一个产品行记录时忘记输入一个UnitP
30、rice值, 与其保存这个结果到数据库,我们还不如给用户显示一个提示信息,自始至终这个页面,任何的对产品的编辑必须指定一个价格。传入到GridView的事件处理程序的GridViewUpdateEventArgs对象包含一个Cancel属性,如果把它设置为true,则中止这个更新过程。让我们扩展RowUpdating事件处理程序,设置e.Cancel为true并显示一个信息说明为什么在NewValues集合里的UnitPrice值为null 。首先,添加一个Label服务器控件到页面并命名为MustProvideUnitPriceMessage 。这个Label控件将显示用户是否在更新一个产品
31、时忘记指定一个UnitPrice值。设置这个Label的Text属性为“您必须为产品提供一个价格。”。我也已经在Styles.css文件中添加了一个名为Warning的新CSS类别,定义如下:?1234567.Warning color: Red; font-style: italic; font-weight: bold; font-size: x-large;最后,设置Label的CssClass属性为Warning 。这样设计器中将在GridView上方显示这个红色、斜体、加粗、并且较大字体的警告信息
32、。图 12: 一个Label控件已被添加到GridView上方默认地,这个Label控件隐藏,那么在Page_Load事件处理程序中设置它的Visible属性为false 。?1234protected void Page_Load(object sender, EventArgs e) MustProvideUnitPriceMessage.Visible = false;如果用户尝试更新一个产品并不指定UnitPrice值,我们希望取消这个更新并显示警告标签。在GridView的RowUpdating事件处理程序中增加如下的代码:?123456789101112131
33、4151617protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e) if (e.NewValues"UnitPrice" != null) e.NewValues"UnitPrice" = decimal.Parse(e.NewValues"UnitPrice".ToStr
34、ing(), System.Globalization.NumberStyles.Currency); else / Show the Label MustProvideUnitPriceMessage.Visible = true; / Cancel the update
35、 e.Cancel = true; 如果一个用户试图保存一个产品并不指定价格,这个更新操作就被取消并显示一个有用的提示信息。虽然数据库(和业务逻辑)允许NULL值的UnitPrice,但这个特定的ASP.NET页面不允许。图 13: 用户不能让UnitPrice为空到目前为止我们看过了如何使用GridView的RowUpdating事件来编程改变赋值到ObjectDataSource的UpdateParameters集合的参数值,还有如何完全地取消这个更新过程。这些思想也可以延展至DetailsView和FormView控件并且应用到插入
36、或删除。这些任务也可以在ObjectDataSource这一层通过的Inserting、Updating和Deleting事件处理程序完成。这些事件在隐含对象的关联方法被调用前触发,并且提供一个更改输入参数集合或者完全取消此操作的最后机会。对应这3个事件的事件处理程序传入一个ObjectDataSourceMethodEventArgs 类型的对象,我们对它的这两个属性感兴趣:·Cancel,它如果被设置为true,取消执行中的操作·InputParameters,它是InsertParameters、UpdateParameters或DeleteParameters的集合
37、,这取决于这是Inserting、Updating、还是Deleting事件的事件处理程序为了举例说明在ObjectDataSource这一层如何处理参数的值,让我们在页面里包含一个DeailsView,它允许用户新增一个新的产品记录。这个DetailsView将用作提供一个快捷的方式添加一个新的产品记录到数据库。为了在新增产品时保持界面一致,我们仅允许用户输入ProductName和UnitPrice字段。作为默认值,这些在DetailsView的插入界面提供的值将被设置为一个数据库的NULL值。不过,我们可以使用ObjectDataSource的Inserting事件注入不同的默认值,正如
38、我们马上要看的。第三步: 提供一个添加新产品的界面在GridView的上方,从工具箱里拖放一个DetailsView控件到设计器,清空它的Height和Width属性,并将它绑定到页面中已经存在的ObjectDataSource 。这将为产品的每一个字段添加一个绑定列或CheckBox列。因为我们希望用这个DetailsView控件来添加新产品,我们需要从它的职能标记里勾选启用插入这一项;然而并没有这一项,这是因为此ObjectDataSource的Insert()方法还没有映射到ProductsBLL类的方法(回想起我们在配置数据源时设置了这个映射为(无) 见图3)。为了再次配置这个Obje
39、ctDataSource,从它的职能标记中选择“配置数据源”的链接,载入向导。第一屏允许你更改ObjectDataSource绑定到的隐含对象;让它依旧是ProductsBLL 。下一屏列出从ObjectDataSource到隐含对象的方法的映射。尽管我们已经明确地指定Insert()和Delete()不映射到任何方法,然而如果你到INSERT和DELETE的tab页你还是会看到那里有一个映射。这是因为ProductsBLL的AddProduct和DeleteProduct方法使用了DataObjectMethodAttribute指出它们分别是为Insert()和Delete()服务的默认的
40、方法。因此,ObjectDataSource向导在每次运行时都会自动地选择它们,除非那里被明确地指定了一个别的值。让Insert()方法依旧指向AddProduct方法,不过再次从DELETE的tab页的下拉列表中选择“(无)”。图 14: 从INSERT的Tab页的下拉列表中选择AddProduct方法图 15: 从DELETE的Tab页的下拉列表中选择(无)完成了这些更改后,该ObjectDataSource的声明语法中将包含一个InsertParameters集合,如下所示:?123456789101112131415161718192021<asp:ObjectDataSourc
41、e ID="ObjectDataSource1" runat="server" SelectMethod="GetProducts" TypeName="ProductsBLL" UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating" InsertMethod="AddProduct" OldValuesPar
42、ameterFormatString="original_0"> <UpdateParameters> <asp:Parameter Name="productName" Type="String" /> <asp:Parameter Name="unitPrice" Type="Decimal" />
43、160;<asp:Parameter Name="productID" Type="Int32" /> </UpdateParameters> <InsertParameters> <asp:Parameter Name="productName" Type="String" /> <asp:Parameter Name=&qu
44、ot;supplierID" Type="Int32" /> <asp:Parameter Name="categoryID" Type="Int32" /> <asp:Parameter Name="quantityPerUnit" Type="String" /> <asp:Parameter Name=&qu
45、ot;unitPrice" Type="Decimal" /> <asp:Parameter Name="unitsInStock" Type="Int16" /> <asp:Parameter Name="unitsOnOrder" Type="Int16" /> <asp:Parameter Name=&quo
46、t;reorderLevel" Type="Int16" /> <asp:Parameter Name="discontinued" Type="Boolean" /> </InsertParameters></asp:ObjectDataSource>再次运行向导导致重新添加OldValuesParameterFormatString属性。把这个属性设置为默认值(0)或者从声明语法中把它们完全删除。随着Object
47、DataSource提供插入数据的能力,现在DetailsView的职能标记里包含“启用插入”的checkbox;回到设计器并勾选这一项。然后,减少DetailsView的列直道它只包含两个绑定列- ProductName和UnitPrice ,还有一个CommandField。此时DetailsView的声明语法将如下所示:?12345678910<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataK
48、eyNames="ProductID" DataSourceID="ObjectDataSource1"> <Fields> <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" /> &
49、#160; <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> <asp:CommandField ShowInsertButton="True" /> </Fields></asp:DetailsView>
50、;图16展现的是在此时通过浏览器查看的页面。正如你所看到的,DetailsView列出第一个产品(Chai)的名称和价格。不过,我们需要的是一个插入界面来提供一个用户快速增加一个新产品到数据库的手段。图16: 该DetailsView当前呈现在只读模式为了展示插入模式的DetailsView我们需要设置DefaultMode属性为Inserting。这让DetailsView在第一次访问和插入一条新纪录之后,它都呈现在插入模式。如图17所示,这样的一个DetailsView提供了一个快捷的界面用以添加新记录。图 17: 这个DetailsView提供了一个快速添加新产品的界面当用户输入一个产品
51、名称和价格(例如“Acme Wate”和1.99,如图17)并点击插入按钮,发生回传并且开始插入的工作流程,直到最后添加一个新产品记录到数据库。DetailsView维持在它的插入界面,并且GridView自动地重现绑定到它的数据源,目的是为了包含新增加的产品,如图18所示。图 18: 产品“Acme Water”已经被添加到数据库虽然图18的GridView中没有显示出来,DetailsView界面里缺少的产品字段 CategoryID、SupplierID、QuantityPerUnit、等等 被赋上一个数据库NULL值。你可以通过履行下面一个步骤来看到这一点:1.到Visual Studio的服务器资源管理器2.展开NORTHWND.MDF数据库节点3.在Products数据表节电上右键点击4.选择“显示表数据”这将列出Products表中的所有记录。如图19所示,除了ProductID、ProductName和UnitPrice字段,我们的新产品的其它字段都为NULL值。图 19: 未在DetailsView中提供的产品
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 茶艺师考试的自信心塑造试题及答案
- 二零二五年度家禽养殖保险及采购保障合同
- 软件专业资格考试结合实际试题与答案
- 2025年度智能物流仓储合同补充协议书模板
- 常见土木工程师试题及答案解析
- 二零二五年度儿童时尚模特拍摄合同模板
- 二零二五年度代驾服务节假日加班费协议
- 2025计算机技术与软件专业初级考试的技术挑战试题及答案
- 实验动物模拟练习题(含参考答案)
- 电工练习题库
- 2020版脊髓性肌萎缩症遗传学诊断专家共识(全文)
- 2024年工作目标和计划新年工作计划目标
- 数字营销对消费者购买决策的影响-洞察分析
- 网络评论的意识形态边界及治理
- TCUWA50054-2023钢结构装配式污水处理设施技术规程
- 诺如病毒课件教学课件
- 2024年国家公务员考试《行测》真题卷(副省级)答案及解析
- 2024年重庆市中考数学真题卷(A)及答案解析
- 小学道德与法治诚信教育
- 天津市部分区2022-2023学年七下期中考试数学试卷(解析版)
- 阴道镜在阴道萎缩性疾病的诊断
评论
0/150
提交评论