在DataKeyNames属性指定的主键的值在第1步中赋值到UpdateParameters,反之非主键的值来自当前编辑行的TextBox服务器控件。如果这一点遗漏了,那么UpdateParameters主键的值在第1步中将被赋上一个值,然后转入第2步中将不会导致任何记录的更新。
编辑功能可以简单地通过勾选GridView的智能标记中的启用编辑从而被激活。
图 15: 勾选启用编辑
勾选启用编辑将添加一个CommandField(如果需要的话)并设置它的ShowEditButton属性为true 。如我们之前所看过的,CommandField包含一些ShowXButton属性,他们指出哪一系列的按钮要显示在CommandField里。在我们的例子里,勾选启用编辑添加ShowEditButton属性到现有的CommandField里:
<asp:GridView runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"> <Columns> <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" /> ... BoundFields removed for brevity ... </Columns> </asp:GridView>
就这样就添加了根本的编辑支持。如图16所示,编辑界面还比较粗糙–每一个非只读的绑定列呈现为一个TextBox。这包括像CategoryID和SupplierID的字段,而它们是来自其它表的外键。
图 16: 点击产品“Chai”的编辑按钮让此行显示为“编辑模式”
为了要求用户直接编辑外键,这个编辑界面还缺少了以下途径:
·如果用户输入一个在数据库中不存在的CategoryID或SupplierID,此更新将违反一个字段间的约束,引发一个异常。
·这个编辑界面不包含任何数据验证。如果你不提供一个必填的值(例如ProductName),或者在要求输入数字的地方输入一个字符串,将抛出一个异常。未来的章节里将研究如何在编辑的用户界面中增加验证控件(给编辑和新增界面增加验证控件)。
·通常,产品的所有非只读字段都必须包含在GridView里。如果我们从GridView里剔除一列,比如说UnitPrice,当更新数据时GridView将不会设置UnitPrice UpdateParameters的值,这将把该数据库记录的UnitPrice值更改为NULL值。类似地,如果一个必填的字段,例如ProductName,从GridView中被剔除了,那么这个更新将失败,并出现一个上文中提及过的“Column 'ProductName' does not allow nulls”异常。
·这个编辑界面遗留了许多必要的格式化的问题。UnitPrice显示为四位小数。理想地CategoryID和SupplierID应该包含下拉列表(DropDownList),它列出系统中存在的类别和供应商。
我们不得不承认现在这还有许多缺点,但这些将在未来的章节里谈及。
在DetailsView中插入、编辑和删除数据
正如我们在之前的章节里看过的,DetailsView控件一次只显示一条记录,就像GridView一样,它也允许对当前显示的记录进行编辑和删除。不管是对最终用户来说从DetailsView进行编辑和删除的体验,还是在ASP.NET这一面的工作流程,都跟GridView是一样的。DetailsView和GridView不同的地方是,它还提供了内键的插入支持。
为了示范DetailsView的数据修改功能,首先,添加一个DetailsView控件到Basics.aspx页面,放在现有的GridView的上方,并通过DetailsView的职能标记把它绑定到现有的ObjectDataSource。然后,清除DetailsView的Height和Width属性,并从它的职能标记中勾选“启用分页”。为了启用编辑、插入和删除支持,只需要简单地从它的职能标记里勾选上“启用插入”、“启用编辑”和“启用删除”。
图 17: 配置DetailsView支持编辑、插入和删除
与GridView一样,添加编辑、插入或删除支持会添加一个CommandField到该DetailsView,如下声明语法所示:
<asp:DetailsView runat="server" AutoGenerateRows="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"> <Fields> <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False" ReadOnly="True" SortExpression="ProductID" /> <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" /> <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" /> <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" /> <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" /> <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" /> <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" /> <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" /> <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" SortExpression="ReorderLevel" /> <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" /> <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" ReadOnly="True" SortExpression="CategoryName" /> <asp:BoundField DataField="SupplierName" HeaderText="SupplierName" ReadOnly="True" SortExpression="SupplierName" /> <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" ShowInsertButton="True" /> </Fields> </asp:DetailsView>