透過手寫程式瞭解GridView的運作

來源:互聯網
上載者:User
緣起:

小喵接觸ASP.NET是從ASP.NET 2.0開始(VS2005),而GridView這個控制項也是從這個時候開始出現,由於有DataSouce的輔助,讓我們在使用上非常的方便。只要拖拉一下,設定一下,資料就可以透過GridView顯示在網頁上了。不過方便的結果,可能用了一段時間,開發了幾套系統,卻還不知道這GridView到底是怎麼運作的(因為通通包裝的好好的)。

這一篇是強迫不使用DataSource(SqlDatasouce,ObjectDataSouce,AccessDataSource,...)的情況下,透過ADO的存取資料庫,以及GridView的各個事件,來理解GridView的一些運作狀況。小喵會在這篇中,寫下有關GridView的資料繫結、編輯、修改、刪除、排序、分頁等功能的程式碼。

準備工作:

此篇範例照慣例,使用北風資料庫當做範例。用最簡單的資料表【Region】來當作範例,當然大家在練習時,可以自己去改掉Connection String與Table名稱。

畫面:

畫面上安排很簡單,就是安排一個GridView,然後隨便選一個樣式(可以分辨編輯實的顏色變化),另外加入一個Templete Fields,用來放置【編輯、刪除、維護、取消】的按鈕。另外再安排一個Button,用來第一次繫結資料。相關程式碼如下:

 

        <asp:Label ID="lblMsg" runat="server" Text=""></asp:Label>        <br />        <asp:Button ID="Button1" runat="server" Text="Button" />        <asp:GridView ID="GridView1" runat="server" AllowSorting="True"             BackColor="White" BorderColor="#E7E7FF" BorderStyle="None" BorderWidth="1px"             CellPadding="3" GridLines="Horizontal" AllowPaging="True" PageSize="3">            <RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />            <Columns>                <asp:TemplateField>                    <EditItemTemplate>                        <asp:Button ID="btnUpdate" runat="server" Text="維護" CommandName="Update" />                        <asp:Button ID="btnCancel" runat="server" Text="取消" CommandName="Cancel" />                    </EditItemTemplate>                    <ItemTemplate>                        <asp:Button ID="btnEdit" runat="server" Text="編輯" CommandName="Edit" />                        <asp:Button ID="btnDel" runat="server" Text="刪除" CommandName="Delete" OnClientClick="return confirm('您確定要刪除此筆資料嗎??');" />                    </ItemTemplate>                </asp:TemplateField>            </Columns>            <FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />            <PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />            <SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />            <HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />            <AlternatingRowStyle BackColor="#F7F7F7" />        </asp:GridView>

後置程式碼:

接著就開始來撰寫程式碼的部分。首先,要手動寫程式了,當然要Imports相關的NameSpance

Imports System.DataImports System.Data.SqlClient

並且設定一下Connection String

Private ConnStr As String = "Data Source=.\sqlexpress;Initial Catalog=Northwind;Integrated Security=True"

接著撰寫【查詢、修改、刪除】資料的Function,用來【讀取、修改、刪除】Region資料表,讀取的Function傳回DataTable。

    Private Function GetData() As DataTable        Dim Dt As New DataTable        Try            Using Conn As New SqlConnection(ConnStr)                Dim SqlTxt As String = ""                SqlTxt += " SELECT TOP 50 * "                SqlTxt += " FROM [Region] (NOLOCK) "                SqlTxt += "  "                Dim Cmmd As New SqlCommand(SqlTxt, Conn)                Dim Da As New SqlDataAdapter(Cmmd)                Da.Fill(Dt)            End Using        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try        Return Dt    End Function    Private Function DeleteData(ByVal RegionID As Integer) As String        Dim rc As String = ""        Try            Using Conn As New SqlConnection(ConnStr)                Conn.Open()                Dim SqlTxt As String = ""                SqlTxt += " DELETE Region "                SqlTxt += " WHERE RegionID = @RegionID "                SqlTxt += "  "                Using Cmmd As New SqlCommand(SqlTxt, Conn)                    Cmmd.Parameters.AddWithValue("@RegionID", RegionID)                    Cmmd.ExecuteNonQuery()                End Using                rc = "Success"            End Using        Catch ex As Exception            rc = "False"            Me.lblMsg.Text = ex.Message        End Try        Return rc    End Function    Private Function UpdData(ByVal RegionID As Integer, ByVal RegionDescription As String) As String        Dim Rc As String = ""        Try            Using Conn As New SqlConnection(ConnStr)                Conn.Open()                Dim SqlTxt As String = ""                SqlTxt += " UPDATE Region "                SqlTxt += " SET RegionDescription = @RegionDescription "                SqlTxt += " WHERE RegionID = @RegionID "                SqlTxt += "  "                Using Cmmd As New SqlCommand(SqlTxt, Conn)                    Cmmd.Parameters.AddWithValue("@RegionDescription", RegionDescription)                    Cmmd.Parameters.AddWithValue("@RegionID", RegionID)                    Cmmd.ExecuteNonQuery()                    Rc = "Success"                End Using            End Using        Catch ex As Exception            Rc = "False"            Me.lblMsg.Text = ex.Message        End Try        Return Rc    End Function

接著陸續來看查詢、編輯、修改、刪除、分頁、排序的各個程式碼:

查詢:當按鈕按下去後,將資料繫結給GridView,因此先寫一個將資料繫結的Sub GVGetData()來處理,未來會有很多地方都要呼叫這一個Sub作繫結資料處理

    '抓取資料並繫結GridView    Private Sub GVGetData()        Try                Dim Dt As DataTable = GetData()                Me.GridView1.DataSource = Dt                Me.GridView1.DataBind()        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try    End Sub

接著,按鈕按下去的時候,只需要呼叫他就可以了

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click        '呼叫資料繫結        GVGetData()    End Sub

接著,再來看分頁如何做。分頁時,要設定GridView的AllowPaging=True,另外,由於這個資料表的資料不多,所以改一下,一頁的筆數預設是10筆,改為3筆(PageSize="3")。此時就會有分頁的功能,不過當換頁時,會觸發【PageIndexChanging】與【PageIndexChanged】這兩個事件。程式碼如下:

    Protected Sub GridView1_PageIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.PageIndexChanged        '顯示PageIndexChanged事件被呼叫到        Response.Write("PageIndexChanged!!")    End Sub    Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging        '設定分頁停在第幾頁        Me.GridView1.PageIndex = e.NewPageIndex        '繫結資料        GVGetData()    End Sub

排序:查詢、分頁有了,接著就是排序。排序的時候,會觸發Sorting與Sorted這兩個事件。不過這個部分稍微麻煩,經測試後發現,在Sorting的e.SortDirection並沒有記住這次順排(Ascending)→下次就逆排(Descending)的狀況,每次取得的e.SortDirection通通都是順排(Ascending)。為了達到第一次點順排,再點一次是逆排,因此要透過ViewState來記錄上次的方式,在加上判斷。

另外,本來的繫結資料時,並沒有排序,只有直接把取得的DataTable給GridView。現在要加上排序的功能了,那麼就要拿DataTable的資料來做排序的動作,這個部分要借用【DataView】的【Sort】來設定,而且DataView也可以當作GridView的資料來源。因此我們改寫一下繫結資料的部分先,然後再寫Sorting與Sorted這兩個事件

繫結資料的部分:

透過多型,希望Sorting的時候要繫結資料呼叫GVGetData的另一個型態

    '有指定排序的抓資料並繫結GridView    Private Sub GVGetData(ByVal pSortDirection As SortDirection, ByVal pSortExpression As String)        Try            Dim Dt As DataTable = GetData()            '設定排序的語法            Dim strSort As String = ""            If pSortDirection = SortDirection.Ascending Then                '如果是順排(A~Z)                strSort = pSortExpression            Else                '逆排的時候(Z~A),加上DESC                strSort = pSortExpression & " DESC"            End If            '使用DataView來做GridView的資料來源            Dim Dv As DataView = Dt.DefaultView            '設定DataView的排序方式            Dv.Sort = strSort            Me.GridView1.DataSource = Dv            Me.GridView1.DataBind()        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try    End Sub

接著是Sorting與Sorted的部分

    Protected Sub GridView1_Sorted(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.Sorted        '顯示Sorted事件備觸發        Response.Write("Sorted!!")    End Sub    Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles GridView1.Sorting        Dim NowSE As String = CType(ViewState("NowSE"), String) '現在的排序欄位        Dim NowSD As SortDirection = CType(ViewState("NowSD"), SortDirection)   '目前的排序方向        If NowSE Is Nothing Then            '如果沒有ViewState,指定e.SortExpression與順排當作預設的欄位與方向            NowSE = e.SortExpression            NowSD = SortDirection.Ascending        Else            '有ViewState時            If NowSE <> e.SortExpression Then                '如果欄位與本來的不同                '指定目前的欄位為e.SortExpression                NowSE = e.SortExpression                '指定目前的排序方向為順排                NowSD = SortDirection.Ascending            Else                '如果欄位與本來相同                If NowSD = SortDirection.Ascending Then                    '當本來為順排→改為逆排                    NowSD = SortDirection.Descending                Else                    '當本來違逆排→改為順排                    NowSD = SortDirection.Ascending                End If            End If        End If        '將得到的欄位與方向,紀錄回ViewState        ViewState("NowSD") = NowSD        ViewState("NowSE") = NowSE        '呼叫繫結資料,並指定排序欄位與方向        GVGetData(NowSD, NowSE)    End Sub

這樣子,排序就OK了。不過小喵發現,這樣子排序配合分頁的切換,由於本來的沒有考慮排序,所以每次分頁一切換,就會弄亂排序的狀況。因此要改一下資料繫結的部分,檢查ViewState中是否有設定排序的欄位與方向。改一下本來的GVGetData()

    '抓取資料並繫結GridView    Private Sub GVGetData()        Try            '判斷是否有排序過            If ViewState("NowSE") Is Nothing Then                '沒有排序過,直接抓DataTable                Dim Dt As DataTable = GetData()                Me.GridView1.DataSource = Dt                Me.GridView1.DataBind()            Else                '排序過,因此除了抓資料,還要排序                Dim NowSE As String = CType(ViewState("NowSE"), String)                Dim NowSD As SortDirection = CType(ViewState("NowSD"), SortDirection)                GVGetData(NowSD, NowSE)            End If        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try    End Sub

這樣無論排序、分頁的部分都可以正常運作了。

接著,就是編輯、修改、刪除的程式碼。這部分小喵發現,在預期的狀況下,修改、刪除的時候,會觸發RowUpdating與RowUpdated / 或者 RowDeleting與RowDeleted。但是實際Step By Step的運作下,令人驚訝的發現,維護後的RowUpdated與修改後的RowDeleted這兩個事件並不會被觸發。這與小喵以往的印象ing:處理中/ed:處理後的理解與期望不同。小喵特別發了一個討論在小舖中【手動寫程式處理GridView的維護,為何沒有觸發RowUpdated事件】,看來GridView沒有使用DataSourceID去繫結DataSource控制項的狀況下,不會觸發這兩個ed的事件

以下為編輯、修改、取消、刪除的程式碼:

刪除資料:

    Protected Sub GridView1_RowDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeletedEventArgs) Handles GridView1.RowDeleted        '顯示RowDeleted備觸發→事實上用程式碼並不會觸發此事件!!        Response.Write("RowDeleted")        'GVGetData()    End Sub    Protected Sub GridView1_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView1.RowDeleting        Try            Dim RegionID As Integer '刪除的Key值            '取得刪除的Key            RegionID = CType(Me.GridView1.Rows(e.RowIndex).Cells(1).Text, Integer)            '呼叫刪除的Function            Dim rc As String = DeleteData(RegionID)            If rc = "Success" Then                Me.lblMsg.Text = "刪除成功!!"                '呼叫繫結資料重新繫結                GVGetData()            End If        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try    End Sub

編輯:

    Protected Sub GridView1_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView1.RowEditing        '設定編輯的Index        Me.GridView1.EditIndex = e.NewEditIndex        '繫結資料        GVGetData()    End Sub

取消:

    Protected Sub GridView1_RowCancelingEdit(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles GridView1.RowCancelingEdit        '取消編輯模式→設定GridView的EditIndex = -1        Me.GridView1.EditIndex = -1        GVGetData()    End Sub

修改:

    Protected Sub GridView1_RowUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs) Handles GridView1.RowUpdated        '離開編輯模式        'Me.GridView1.EditIndex = -1        'GVGetData()        Response.Write("RowUpdated")    End Sub    Protected Sub GridView1_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView1.RowUpdating        Try            Dim RegionID As Integer            Dim RegionDescription As String            '取得畫面中的資料            Dim tGvRw As GridViewRow = Me.GridView1.Rows(e.RowIndex)            RegionID = CType(CType(tGvRw.Cells(1).Controls(0), TextBox).Text, Integer)            RegionDescription = CType(tGvRw.Cells(2).Controls(0), TextBox).Text            '進行維護            Dim Rc As String = UpdData(RegionID, RegionDescription)            If Rc = "Success" Then                Me.lblMsg.Text = "維護成功"                '離開編輯模式                Me.GridView1.EditIndex = -1                GVGetData()            End If        Catch ex As Exception            Me.lblMsg.Text = ex.Message        End Try    End Sub

後記

再經過這樣的練習後,對於GridView的一些運作,會有比較清楚了瞭解。據說這樣的能力在以前DataGrid的時代,是基本的能力,也就是大家都必須這麼寫。自從ASP.NET 2.0開始,GridView搭配DataSource控制項實在太好用了。簡單的使用SqlDataSource只需要拖拉、設定就可以通通達成。進一步需要透過程式處理,也可以寫成Class透過ObjectDataSource來達成。不過,當系統的需求越來越複雜,有時候就需要去透過GridView各項事件去處理一些狀況。透過這樣的練習可以來瞭解一下各個事件的用法。小喵因此將過程筆記下來,也提供大家參考。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.