了解GridView事件(Event)

GridView實在是非常好入門的控制項,讓我們可以知一解百,也就是說,你如果能完全了解GridView控制項,那其他類似的資料處理控制項你也差不多學完了,所以對GridView的投資是非常值得。

除了要好好了解拉放之間滑鼠及Vistual Studio帶來的便利,我覺的學好GridView 事件,對學習ASP.NET有更重大的意義,一般控制項了不起就是Page_Load、Click、Change、Select這幾類,但GridView不同,因為它能幫你做好多好多事,所以他的事件就複雜很多,複雜不代表難。

GridView的事件多數都有前後之分(ing或ed結尾),這樣的事件流程讓我們可以對整個控制項或資料處理上有更靈活的操作,例如我要進行刪除作業:

刪除前 → 刪除中 → 刪除後

除了刪除中是我們無法操作的(因為刪除動作是在資料庫),我們可以在刪除前先做個Double Check,刪除後再Check一次及提示訊息。這是以前ASP所做不到的。「事件」可以說是ASP.NET一個很大的優勢,以下針對GridView事件做一個整理,而且每一個事件裡都把常用參數整理好,再加上一個小小範例,以後有GridView方面事件的問題,就可以直接查這篇,可以當成GridView事件快速入門篇。




RowCreated事件

''' <summary>
    ''' 建立 GridView 控制項中的資料列時發生。 
    ''' <summary>
    ''' <remarks>必須先為控制項中的每個資料列建立 GridViewRow  物件,才能呈現 GridView 控制項。建立 GridView 控制項中的每個資料列時,會引發 RowCreated  事件。</remarks>
    Protected Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowCreated
        'e.Row:取得所建立或繫結(Binding)到資料的資料列。 
        'e.Row.Cells(i):i是數值,存取資料列的第i個儲存格。
        'e.Row.RowType:在執行作業之前判斷資料列的型別。
        '範例:http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.gridview.rowcreated%28v=VS.80%29.aspx
    End Sub

RowCommand事件(常用)

''' <summary>
    ''' 按一下 GridView 控制項中的按鈕時發生。 
    ''' </summary>
    Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
        '通常判斷e.CommandName與e.CommandArgument來進行一些額外的事件處理
        'e.CommandName有些內建關鍵字,會引發特定行為與事件(http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.gridview.rowcommand%28v=VS.80%29.aspx)
        'e.CommandName:取得自訂按鈕命令名稱
        'e.CommandArgument:取得自訂按鈕命令引數
        'e.CommandSource:存取引發事件的按鈕控制項

        '自訂按鈕,命令名稱為"cancelSelected"
        If e.CommandName = "cancelSelected" Then
            GridView1.SelectedIndex = -1
        End If
    End Sub

我們自訂的命令名稱都需要在RowCommand事件做處理。例如GridView沒有取消選取的功能,我們就可以自訂按鈕,然後命名為cancelSelected,然後在RowCommand事件來進行取消選取的功能。

RowDataBound事件

''' <summary>
    ''' 資料列繫結(Binding)至 GridView 控制項中的資料時發生。 
    ''' </summary>
    ''' <remarks>控制項中的每個資料列必須都繫結(Binding)至資料來源中的資料錄,才能呈現 GridView  控制項。資料列 (由 GridViewRow  物件表示) 繫結(Binding)至 GridView 控制項中的資料時,會引發 RowDataBound 事件。這可讓您提供事件處理方法,用於每次發生這個事件時執行自訂常式,例如修改繫結(Binding)至資料列之資料的值。GridViewRowEventArgs 物件會傳遞至事件處理方法,讓您存取正在繫結(Binding)之資料列的屬性。若要存取資料列中的特定儲存格,請使用 GridViewRowEventArgs 物件的 Cells 屬性。您可以使用 RowType 屬性決定繫結(Binding)那種資料列型別 (標頭資料列、資料列等)。</remarks>
    Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
        'e.Row:取得所建立或繫結(Binding)到資料的資料列。 
        'e.Row.Cells(i):i是數值,存取資料列的第i個儲存格。
        'e.Row.RowType:在執行作業之前判斷資料列的型別。
        '1. DataRow:GridView 控制項中的資料列。(常用)
        '2. Footer:GridView 控制項的頁尾資料列。
        '3. Header:GridView 控制項的標頭資料列。
        '4. EmptyDataRow:GridView 控制項中的空白資料列。
        '5. Pager:GridView 控制項中的頁面巡覽列。
        '6. Separator:GridView 控制項中的分隔列。

        '如果資料的類型是「資料列DataRow」,第一個儲存格文字改為粗體。
        If e.Row.RowType = DataControlRowType.DataRow Then
            e.Row.Cells(1).Text = "<b>" & e.Row.Cells(1).Text & "</b>"
        End If
    End Sub

例如我們想幫GridView的每個刪除按鈕加上一段JavaScript,就必須寫在這裡。想像成DataSource把資料一列一列送給GridView,而每一列資料與資料列綁定時,就會發生RowDataBound事件(一列發生一次),所以如果你想做的事是對整個GridView產生作用(每個刪除按鈕),那就必須寫在RowDataBound事件。

刪除事件

''' <summary>
    ''' 按一下資料列的 [刪除] 按鈕時發生 (但在 GridView 控制項刪除資料列之前)。 
    ''' </summary>
    Protected Sub GridView1_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView1.RowDeleting
        'e.Keys:取得欲刪除那筆資料的PK值。查看DataKeyNames屬性,就可以知道PK值有那些。
        'e.Cancel:Boolean,True表示取消刪除動作。
        'e.Values:取得要刪除那筆資料的"欄位值"
        'e.RowIndex:目前要刪除這筆資料在GridView中的索引值。注意,Index及PK是不同東西。Index指的是排序順序,另外GridView有啟用分頁,假設每頁10筆,則第2頁第一筆資料的RowIndex是0非10。

        If e.Keys("CustomerID") = "ALFKI" Then
            Response.Write("此資料不能刪除!")
            e.Cancel = True
        End If
    End Sub

如果你想手寫刪除程式,必須寫在RowDeleting事件。

''' <summary>
    ''' 按一下資料列的 [刪除] 按鈕時發生 (但在 GridView 控制項刪除資料列之後)。
    ''' </summary>
    Protected Sub GridView1_RowDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeletedEventArgs) Handles GridView1.RowDeleted
        'e.AffectedRows:刪除筆數。
        'e.Keys:取得欲刪除那筆資料的PK值。
        'e.Values:取得要刪除那筆資料的"欄位值"。
        'e.Exception:若刪除發生例外,可透過e.Exception取得例外相關資訊。
        'e.ExceptionHandled:Boolean,當例外發生且e.ExceptionHandled沒有為True時,會值接在網頁上顯示例外的錯誤畫面。

        '確認是否有刪除例外發生
        If e.Exception Is Nothing Then
            Response.Write("刪除" & e.AffectedRows & "筆資料:" & e.Keys("CustomerID") & "," & e.Values("CompanyName"))
        Else
            '不要產生錯誤畫面
            e.ExceptionHandled = True
            Response.Write(e.Exception.Message)
        End If
    End Sub

編輯事件

''' <summary>
    ''' 按一下資料列的 [編輯] 按鈕時發生 (但在 GridView 控制項進入編輯模式之前)。 
    ''' </summary>
    ''' <remarks>RowEdit沒有ed事件(RowEdited),因為進入Edit模式後,是由RowUpdating/RowUpdated接手處理。</remarks>
    Protected Sub GridView1_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView1.RowEditing
        'e.Cancel:Boolean,True表示取消編輯動作。
        'e.NewEditIndex:取得或設定要編輯之資料列的索引。

        '按下「編輯」按鈕的這一資料列(e.NewEditIndex)進入編輯模式
        GridView1.EditIndex = e.NewEditIndex
    End Sub

''' <summary>
    ''' 按一下處於編輯模式之資料列的 [取消] 按鈕時發生 (但在資料列結束編輯模式之前)。 
    ''' </summary>
    Protected Sub GridView1_RowCancelingEdit(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles GridView1.RowCancelingEdit
        'e.Cancel:Boolean,True表示取消編輯模式。
        'e.RowIndex:目前要取消這筆資料在GridView中的索引值。

        '取消編輯模式
        'e.Cancel = True 
        '在VB中「-1」(負1)也有取消的意思
        GridView1.EditIndex = -1
    End Sub

更新事件

''' <summary>
    ''' 按一下資料列的 [更新] 按鈕時發生 (但在 GridView 控制項更新資料列之前)。 
    ''' </summary>
    Protected Sub GridView1_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView1.RowUpdating
        'e.Keys:取得欲更新那筆資料的PK值。
        'e.Cancel:True表示取消更新動作。
        'e.OldValues:取得更新那筆資料,除了PK欄位之外的原始值。
        'e.NewValues:取得欲更新那筆資料,除了PK欄位之外的更新值。
        'e.RowIndex:目前要更新這筆資料在GridView中的索引值。

        Dim cmpName As String = Trim(e.NewValues("CompanyName"))
        If cmpName.Length = 0 Then
            Response.Write("公司名稱不可為空白")
            e.Cancel = True
        End If
    End Sub

利用更新前做一些錯誤處理,避免不正確的資料進到資料庫中。或是手寫更新程式,也必須寫在這裡。

''' <summary>
    ''' 按一下資料列的 [更新] 按鈕時發生 (但在 GridView 控制項更新資料列之後)。 
    ''' </summary>
    Protected Sub GridView1_RowUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs) Handles GridView1.RowUpdated
        'e.AffectedRows:更新筆數。
        'e.Keys:取得欲更新那筆資料的PK值。
        'e.OldValues:取得更新那筆資料,除了PK欄位之外的原始值。
        'e.NewValues:取得欲更新那筆資料,除了PK欄位之外的更新值。
        'e.KeepInEditMode:Boolean,是否讓GridView維持在編輯模式。
        'e.Exception:若更新發生例外,可透過e.Exception取得例外相關資訊。
        'e.ExceptionHandled:Boolean,當例外發生且e.ExceptionHandled沒有為True時,會值接在網頁上顯示例外的錯誤畫面。

        If e.Exception Is Nothing Then
            Response.Write("成功更新 " & e.AffectedRows & " 筆資料.")
        Else
            e.ExceptionHandled = True
            Response.Write(e.Exception.Message)
            e.KeepInEditMode = True
        End If
    End Sub

分頁事件

''' <summary>
    ''' 按一下其中一個頁面巡覽區按鈕時發生 (但在 GridView 控制項處理分頁作業之前)。 
    ''' </summary>
    ''' <remarks>以程式設計的方式設定 PageIndex  屬性時,不會引發這個事件。</remarks>
    Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging
        'e.Cancel:Boolean,True表示取消分頁選取模式。
        'e.NewPageIndex:取得或設定要在 GridView  控制項中顯示的新頁面索引。

        '按下「分頁」選擇,讓GridView顯示指定的分頁(e.NewPageIndex)
        GridView1.PageIndex = e.NewPageIndex
    End Sub

''' <summary>
    ''' 按一下其中一個頁面巡覽區按鈕時發生 (但在 GridView  控制項處理分頁作業之後)。 
    ''' </summary>
    Protected Sub GridView1_PageIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.PageIndexChanged
        '在產生「Page 1 of 10 .」的提示資訊。
        Response.Write("Page " & (GridView1.PageIndex + 1).ToString() & " of " & GridView1.PageCount.ToString() & ".")
    End Sub

選取


''' <summary>
    ''' 按一下資料列的 [選取] 按鈕時發生 (但在 GridView 控制項處理選取作業之前)。 
    ''' </summary>
    ''' <remarks>以程式設計的方式設定 SelectedIndex  屬性時,不會引發這個事件。</remarks>
    Protected Sub GridView1_SelectedIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSelectEventArgs) Handles GridView1.SelectedIndexChanging
        'e.NewSelectedIndex:取得或設定要在 GridView  控制項中選取之新資料列的索引。
        'e.Cancel:Boolean,True表示取消選取事件。

        '按下「選取」按鈕的這一資料列(e.NewSelectedIndex)進入選取模式
        GridView1.SelectedIndex = e.NewSelectedIndex
        '另一種寫法
        'GridView1.SelectedIndex = GridView1.SelectedIndex
    End Sub

''' <summary>
    ''' 按一下資料列的 [選取] 按鈕時發生 (但在 GridView 控制項處理選取作業之後)。 
    ''' </summary>
    Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.SelectedIndexChanged
        '在選取完成後,顯示所選取資料列第三個儲存格(Cells從0開始計算)的資料。
        Response.Write("You selected: " & GridView1.SelectedRow.Cells(2).ToString() & ".")
    End Sub

排序事件

''' <summary>
    ''' 按一下排序資料行的超連結時發生 (但在 GridView 控制項處理排序作業之前)。
    ''' </summary>
    ''' <remarks>按一下排序資料行的超連結時,會引發 Sorting 事件 (但在 GridView 控制項處理排序作業之前)。</remarks>
    Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles GridView1.Sorting
        'e.Cancel:Boolean,True表示取消排序事件。
        'e.SortDirection:取得或設定排序 GridView  控制項的排序方向。
        'e.SortDirection.Ascending():小到大,A~Z。
        'e.SortDirection.Descending():大到小:Z~A。
        'e.SortExpression:取得或設定運算式,用來排序 GridView 控制項中的項目。

        '切換大小排序
        If e.SortDirection = SortDirection.Ascending Then
            e.SortDirection = SortDirection.Descending
        Else
            e.SortDirection = SortDirection.Ascending
        End If

        '欄位Brithday不能排序
        If e.SortExpression = "Birthday" Then
            e.Cancel = True
            Response.Write("You cannot sort by Birthday.")
        End If
    End Sub

''' <summary>
    ''' 按一下排序資料行的超連結時發生 (但在 GridView 控制項處理排序作業之後)。 
    ''' </summary>
    Protected Sub GridView1_Sorted(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.Sorted
        '顯示排序方法及排序欄位
        Response.Write("Sorting by " & GridView1.SortExpression.ToString() & " in " & GridView1.SortDirection.ToString() & " order.")
    End Sub

7 則留言:

  1. 您好,謝謝您的文章,受益良多

    對ROWEDITING事件中這行程式碼有些疑問
    GridView1.EditIndex = e.NewEditIndex

    不過按下編輯按鈕不是就進入編輯模式了嗎,為什麼還需要這行呢?

    謝謝!

    回覆刪除
  2. 那只是範例程式碼,沒有很完整。
    這些事件主要是"手動"/"客製"時,比較容易碰到。
    那行的意思是,在GridView裡的"哪一行"進行入編輯模式。

    有些動作,控制項會有預設行為,以上文章只是想表達每一事件裡的動作,如果不透過預設行為,那我們要怎麼寫,清楚之後,你對GridView之類的控制項才更有掌控能力。

    回覆刪除
  3. 謝謝您的解說,還是不太懂...

    意思是說
    其實編輯的按鈕的所作的事情和GridView1.EditIndex = e.NewEditIndex這行代表的意思相同嗎

    初學者問題有點多 囧

    回覆刪除
    回覆
    1. 是的。
      未來如果控制項玩久了,你就會天天和這些事件在一起了。^_^

      刪除
  4. 不好意思,再問一個問題

    我在GridView裡面加入一個按鈕(CommandName=edit_btn),按下這個按鈕可以使該列進入編輯狀態

    在RowCommand事件裡面寫了以下程式碼

    if(e.CommandName == "edit_btn")
    {
    GridView1.EditIndex = GridView1.SelectedIndex;
    }
    我知道哪邊錯了,但我不知道怎麼改才能達到效果:(

    雖然我知道這不實際,但我還是想知道怎麼做...

    問題好像有點笨...

    回覆刪除
    回覆
    1. 我知道哪邊錯了 <-- 請問你錯在那裡?為什麼錯?

      刪除
  5. 請問如果用selected再提取資料後先做一些運算,再把運算後的值丟到Gridview中顯示有範例嗎?
    或是可以提取資料庫欄位中的兩個值先做一些運算在顯示到Gridview上呢?

    回覆刪除

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。