考察DataGrid控件 Part 6

考察DataGrid控件 Part 6

考察DataGrid控件  Part 6 (上)

本文英文原版:
http://aspnet.4guysfromrolla.com/articles/071002-1.aspx


名词解释
inline:一种处理数据的方法,即这些数据事先不必经过编辑或分类排序,按照它们到达 的顺序,按次序排队处理,参见http://www.iciba.com/search?s=inline


导言:

  在前面的文章里我们考察了如何对DataGrid的结果进行排序,以及如何自定义HTML输出格式.此外,我们可以通过DataGrid方便地检索XML数据。本文,我们考察DataGrid的另一项有用的特点—inline编辑(inline editing)
 

在很多情况下,我们需要在DataGrid里编辑数据。比如,在一个data-driven网站,你可能有一组administrative Web pages页面,这些页面包含了各种不同类型的数据库表(database tables),并允许管理员修改这些表格里的数据。通过DataGrid,我们可以很轻松的将数据库表的信息显示出来(更多信息请参考 Part 2和Part 5),同样,我们也可以用DataGrid来编辑数据!


使用DataGrid的编辑功能(editing features)是很简单的,相比较而言,为了达到相同的目的,DataGrid所需要的代码比经典ASP页面要少地多.此外,在阅读本文之前,你应该对SQL有所了解,也即相关的构建和更新命令(可以参考官方的SQL在线书籍:http://www.microsoft.com/sql/techinfo/productdoc/2000/books.asp)同样的,你也应该对DataGrid控件本身比较了解,理解其事件(events)处理机制,为次可参考本系列的Part 3部分。


首先:显示数据

在我们将注意力集中到编辑DataGrid里的数据之前,我们首先要将数据用DataGrid显示出来。在前面的文章我们已经深入的探讨过这个问题,在此我不打算花过多笔墨。在本例中我们使用的是GrocerToGo数据库(它是一种Access 2000的数据库,可以在本文结束处下载).在此,我们将要显示(并允
是Products里的数据。

我们将在DataGrid里显示Products表里的如下几个列:ProductID, UnitPrice, ProductName,以及ProductDescription,为了使DataGrid看起来比较美观,还包含了一些界面格式代码,下面的代码将Products表的数据显示在DataGrid:

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script runat="server">
  Sub Page_Load(sender as Object, e as EventArgs)
   If Not Page.IsPostBack
      BindData()
   End If
  End Sub


  Sub BindData()
    '1. Create a connection
    Const strConnStr as String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                                        "Data Source=C:/GrocerToGo.mdb"
    Dim objConn as New OleDbConnection(strConnStr)
    objConn.Open()
     
    '2. Create a command object for the query
    Const strSQL as String = "SELECT * FROM Products"
    Dim objCmd as New OleDbCommand(strSQL, objConn)
     
    '3. Create/Populate the DataReader
    Dim objDR as OleDbDataReader
    objDR = objCmd.ExecuteReader()   
     
    dgProducts.DataSource = objDR
    dgProducts.DataBind()  
  End Sub
</script>

<asp:DataGrid id="dgProducts" runat="server"
    AutoGenerateColumns="False" CellPadding="4"
    HeaderStyle-BackColor="Black"
    HeaderStyle-ForeColor="White"
    HeaderStyle-HorizontalAlign="Center"
    HeaderStyle-Font-Bold="True">
       
    <Columns>
        <asp:BoundColumn HeaderText="Product ID" DataField="ProductID" />
        <asp:BoundColumn HeaderText="Price" DataField="UnitPrice"
                ItemStyle-HorizontalAlign="Right"
                DataFormatString="{0:$#,###.##}" />
        <asp:BoundColumn HeaderText="Name" DataField="ProductName" />
        <asp:BoundColumn HeaderText="Description"
                DataField="ProductDescription" />                       
    </Columns>       
</asp:DataGrid>

上述代码浅显易懂,BindData()函数读取Products表的数据到一个DataReader,然后绑定到一个名为dgProducts的DataGrid。


留意Page_Load事件处理器
我们注意到在Page_Load事件处理器里,只有当初次登录页面时,才调用BindData()子程序.也就是说,当页面产生回传时并不会调用BindData()子程序,这是非常关键的!如何你进行修改,每次登录页面时都调用BindData(),你编辑的数值就不会保存在数据库里。欲知详情请参考常见问题答疑:Why Your DataGrid's Updates Don't Show Up。(相关链接为http://datawebcontrols.com/faqs/Editing/EditedValuesNotSaved.shtml

现在我们将数据显示在DataGrid里,接下来我们要对数据进行编辑。在DataGrid里有一个名为EditCommandColumn的控件,其在DataGrid的每一行显示一个"Edit" 按钮。EditCommandColumn控件是如何允许最终用户编辑某一特定行的呢?我们将在下半部分阐述。


考察DataGrid控件  Part 6 (中)

本文英文原版:
http://aspnet.4guysfromrolla.com/articles/071002-1.2.aspx

在上半部分我们阐述了如何将Products表的数据显示在DataGrid里,在本文我们考察如何允许用户编辑DataGrid里的某一特定行。


允许最终用户编辑DataGrid里的某一行

为了让用户编辑DataGrid里的某一行,我们需要一些途径供用户选择他想编辑的行。就像在Part 3 探讨的一样,我们可以使用ButtonColumn控件为DataGrid里的每一行提供一个可点击的按钮。诚然,这样也可以达到编辑的目的,但看起来会有一点凌乱。幸好,DataGrid提供了EditCommandColumn控件以实现该功能。

EditCommandColumn控件在DataGrid里新添一列,为每一行记录放置一个编辑按钮,当点击该按钮时,将引起页面回传并触发EditCommand事件。就像稍后你将看到的那样,我们需要为这个事件写代码。现在让我们看看如何用EditCommandColumn控件为DataGrid添加编辑按钮。很简单,就像添加BoundColumn或ButtonColumn控件一样:

<asp:DataGrid id="dgProducts" runat="server"
   AutoGenerateColumns="False" CellPadding="4"
   HeaderStyle-BackColor="Black"
   HeaderStyle-ForeColor="White"
   HeaderStyle-HorizontalAlign="Center"
   HeaderStyle-Font-Bold="True">
       
   <Columns>
    <asp:EditCommandColumn EditText="Edit Info"
          ButtonType="PushButton"
          UpdateText="Update" CancelText="Cancel" />

       <asp:BoundColumn HeaderText="Product ID" DataField="ProductID"
               ReadOnly="True" />               
       <asp:BoundColumn HeaderText="Price" DataField="UnitPrice"
               ItemStyle-HorizontalAlign="Right"
               DataFormatString="{0:$#,###.##}" />
       <asp:BoundColumn HeaderText="Name" DataField="ProductName" />
       <asp:BoundColumn HeaderText="Description"
               DataField="ProductDescription" />                       
   </Columns>       
</asp:DataGrid>

EditCommandColumn控件有很多可选属性,比如:ButtonType,它指定按钮类型为超链接(默认为LinkButton)或PushButton;以及为Edit, Update和Cancel按钮指定text的 EditText, UpdateText和CancelText属性;此外,还有其它各种的显示属性,比如HeaderText, ItemStyle等等。

如果你仔细的阅读上述代码,你可能会很吃惊EditCommandColumn控件居然会有UpdateText和CancelText属性。毕竟我只提及过EditCommandColumn控件提供编辑按钮。准确的说,除了要编辑的那一行外,每一行都包含一个编辑按钮,而要编辑的那一行却显示的是2个按钮,Update"和"Cancel"按钮。


选择一行供编辑

DataGrid有一个名为EditItemIndex的属性,它指定那一行记录要编辑。DataGrid从0开始为它包含的行记录排顺序。默认情况下,当没有哪行记录要编辑时EditItemIndex的值为-1.当我们点击某行记录的"Edit"时,将触发EditCommand事件处理器。在该事件处理器里,我们将EditItemIndex属性与要编辑的那一行对应起来,然后重新绑定DataGrid的数据(调用BindData()),代码看起来像下面的这样:

Sub dgProducts_Edit(sender As Object, e As DataGridCommandEventArgs)
    dgProducts.EditItemIndex = e.Item.ItemIndex
    BindData()
End Sub


将该事件处理器与EditCommand事件对应起来,在DataGrid里进行指定,如下:

<asp:DataGrid id="dgProducts" runat="server"
   ...  
   OnEditCommand="dgProducts_Edit"
   ... >
       
   <Columns>
       ...
   </Columns>       
</asp:DataGrid>


有了这些代码,当用户点击"Edit"按钮时,页面发生回传,待编辑行的"Edit" 按钮替换成了"Update"和"Cancel"按钮。另外,方格里的数值由文本值(textual value)自动的转换成处于可编辑的textbox类型的数值了。就像下面图像显示的那样。

                  

 

如果你自己在做练习的话,你可能会发现结果与图片有2处不同。首先,在你的机器上编辑行的所有列都转变成了textbox,而图片的ProductID列却不是textbox,也即不可编辑。显然,在某些情况下我们想让某些数据处于只读状态,好比ProductID,它是Products表的关键字段。要想使DataGrid里的某些列不可编辑,我们只需要将其ReadOnly属性设置为True。比如:
asp:DataGrid id="dgProducts" runat="server"
   ... >
       
   <Columns>
      <asp:BoundColumn HeaderText="Product ID" DataField="ProductID"
            ReadOnly="True" />
      ...
   </Columns>       
</asp:DataGrid>

第二个不同点是,本文图片里处于编辑状态的行的颜色要稍微浅淡点。你可以为处于编辑状态的行设置各种各样的格式属性,方法是使用DataGrid的EditItemStyle属性。比如:

<asp:DataGrid id="dgProducts" runat="server"
   ...  
   EditItemStyle-BackColor="#eeeeee"
   ... >
       
   <Columns>
       ...
   </Columns>       
</asp:DataGrid


自此,我们考察了如何选择一行来编辑,接下来我们考察当用户对处于编辑状态的行进行更新或取消更新时,如何添加代码应对。我们将在下一节探讨。

 

考察DataGrid控件  Part 6 (下)
本文英文原版:
http://aspnet.4guysfromrolla.com/articles/071002-1.3.aspx

在上节我们考察了编辑某行所必需的代码,在这一节我们探讨用户更新或取消更新所必需的代码.取消“Cancel”按钮如前所述,当点击某行的"Edit"按钮时,它会被替换为"Update"和"Cancel" 按钮."Cancel" 意味着DataGrid恢复到“非编辑”状态,并不会保存所做的任何修改。当点击"Cancel"按钮时触发CancelCommand事件.在对应的事件处理器里我们需要设置DataGrid返回到“预编辑”(pre-editing)状态。为此,我们只需要将EditItemIndex属性设为“-1”,并重新对DataGrid进行绑定(调用BindData()):

Sub dgProducts_Cancel(sender As Object, e As DataGridCommandEventArgs)
    dgProducts.EditItemIndex = -1
    BindData()
End Sub

更新“Update” 按钮

当点击“Update” 按钮时触发UpdateCommand事件。在对应的事件处理器里,我们需要读取用户键入textboxe的值,然后构造一个恰当的SQL语句。“Update” 按钮的事件处理器接受2个输入参数,一个为Object,另一个为DataGridCommandEventArgs.并且后者有一个Item属性,它是DataGridItem的一个实例,与要编辑的那个DataGrid row相对应。DataGridItem包含一个单元集(Cells collection),可以通过它来访问DataGrid里各种列包含的text或控件.通过DataGridItem对象,我们可以探测所编辑行的ProductID,甚至用户输入textboxe里的price, name,description值:

Sub dgProducts_Update(sender As Object, e As DataGridCommandEventArgs)
   'Read in the values of the updated row
   Dim iProductID as Integer = e.Item.Cells(1).Text
   Dim dblPrice as Double = CType(e.Item.Cells(2).Controls(0),

TextBox).Text
   Dim strName as String = CType(e.Item.Cells(3).Controls(0),

TextBox).Text
   Dim strDesc as String = CType(e.Item.Cells(4).Controls(0),

TextBox).Text

    ...

在编辑模式里,ProductID列并不是textbox类型的(因为它被标明为只读ReadOnly)。我们注意到在代码里ProductID的值可以通过e.Item.Cells(1)的Text属性来获取。Cells(1)代表的是DataGrid row里的第二个表格单元(TableCell)。而第一个表格单元(也就是Cells(0))就是包含 "Update"和 "Cancel"按钮的那个列。

要获取price, name,description的值就要稍微复杂一些,因为这些值是包含在表格单元里的textbox的文本值。因此,我们要用CType函数将相应表格单元的第一个控件(Controls(0))转换(cast)为一个TextBox控件,然后引用它的Text属性。(如果你用的是C#,你要这样转换:((TextBox) e.Items.Cells[2].Controls[0]).Text,而CType()函数是VB.NET的内置函数)

获取这些值以后我们创建一个SQL UPDATE命令。在前面的文章里我们用的是动态SQL语句(dynamic SQL statement),不过在这里我用的是带参数的形式,因为我觉得这样要更简洁一些——当然,你喜欢用哪种都可以。

...
       
    'Construct the SQL statement using Parameters
    Dim strSQL as String = _
      "UPDATE [Products] SET [ProductName] = @ProdName, " & _
      "[UnitPrice] = @UnitPrice, [ProductDescription] = @ProdDesc " &

_
      "WHERE [ProductID] = @ProductID"

    Const strConnString as String = _
       "Provider=Microsoft.Jet.OLEDB.4.0;Data

Source=C:/GrocerToGo.mdb"
    Dim objConn as New OleDbConnection(strConnString)
    objConn.Open()

    Dim myCommand as OleDbCommand = new OleDbCommand(strSQL, objConn)
    myCommand.CommandType = CommandType.Text

    ' Add Parameters to the SQL query
    Dim parameterProdName as OleDbParameter = _
               new OleDbParameter("@ProdName", OleDbType.VarWChar, 75)
    parameterProdName.Value = strName
    myCommand.Parameters.Add(parameterProdName)

    Dim parameterUnitPrice as OleDbParameter = _
               new OleDbParameter("@UnitPrice", OleDbType.Currency)
    parameterUnitPrice.Value = dblPrice
    myCommand.Parameters.Add(parameterUnitPrice)

    Dim parameterProdDesc as OleDbParameter = _
               new OleDbParameter("@ProdDesc", OleDbType.VarWChar)
    parameterProdDesc.Value = strDesc
    myCommand.Parameters.Add(parameterProdDesc)

    Dim parameterProdID as OleDbParameter = _
               new OleDbParameter("@ProductID", OleDbType.Integer)
    parameterProdID.Value = iProductID
    myCommand.Parameters.Add(parameterProdID)

    myCommand.ExecuteNonQuery()   'Execute the UPDATE query
   
    objConn.Close()   'Close the connection
 
  ...


现在,数据库已经对用户的编辑进行了更新,剩下要做的是使DataGrid返回预编辑状态(通过设置EditItemIndex为-1),然后对DataGrid进行绑定(通过BindData())。

...
  
   'Finally, set the EditItemIndex to -1 and rebind the DataGrid
    dgProducts.EditItemIndex = -1
    BindData()       
End Sub

最后,完善代码,你需要将CancelCommand和UpdateCommand事件与相应的事件处理器对应起来,像下面这样:

<asp:DataGrid id="dgProducts" runat="server"
   ...  
   OnUpdateCommand="dgProducts_Update"
   OnCancelCommand="dgProducts_Cancel"
   ... >
       
   <Columns>
       ...
   </Columns>       
</asp:DataGrid>

结语:

综上所述,DataGrid控件不仅可以显示数据,也可以对数据进行编辑。为DataGrid添加该功能相对而言要简单一些,我们真正要话功夫的是编写"Update" 按钮触发的事件的代码。不过话说回来,要实现相同的功能,经典ASP应用程序需要写的代码要多的多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值