GridView+FormView 示範資料 新增/修改/刪除(進階篇:伺服器控制項)

GridView+FormView 示範資料 新增/修改/刪除(進階篇:伺服器控制項)

摘要

承上一篇文章「GridView+FormView 示範資料 新增/修改/刪除」,有人詢問是否能簡化程式碼;答案是可行的,方法就是由伺服器控制項下手。在此文章中,我們將擴充 GridView 及 FormView 控制項,在 GridView 控制項中新增 FormViewID 屬性,關連至指定的 FormView 控制項 ID,就可以輕易達到上篇文章中相同效果。

image

 

擴充 GridView 控制項

首先我們繼承 GridView 下來擴充功能,新增 FormViewID 屬性,用來設定連結的 FormView 控制項 ID。然後把原本在 GridView 的 RowCommand 事件中的程式碼,搬至 OnRowCommand 覆寫方法中。

擴充功能的 TBGridView 控制項完整程式碼如下,其中 OnLoad 方法中,會去判斷 FormView 若為 TBFormView (擴充功能的 FormView),會去設定其 GridView 屬性。

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Drawing

Namespace WebControls
    < _
    Description("TBGridView 控制項"), _
    ToolboxData("<{0}:TBGridView runat=server></{0}:TBGridView>") _
    > _
    Public Class TBGridView
        Inherits GridView
        Private FFormViewID As String = String.Empty
        Private FFormView As FormView = Nothing

        ''' <summary>
        ''' 連結的 FormView 控制項 ID。
        ''' </summary>
        < _
        Description("連結的 FormView 控制項 ID。"), _
        Themeable(False), _
        IDReferenceProperty(GetType(FormView)), _
        TypeConverter(GetType(TBFormViewIDConverter)), _
        Category("Data"), _
        DefaultValue("") _
        > _
        Public Property FormViewID() As String
            Get
                Return FFormViewID
            End Get
            Set(ByVal value As String)
                FFormViewID = value
            End Set
        End Property

        ''' <summary>
        ''' 連結的 FormView 控制項。
        ''' </summary>
        Protected Friend ReadOnly Property FormView() As FormView
            Get
                If String.IsNullOrEmpty(FFormViewID) Then Return Nothing
                If FFormView Is Nothing Then
                    FFormView = CType(Me.Parent.FindControl(FFormViewID), FormView)
                End If
                Return FFormView
            End Get
        End Property

        ''' <summary>
        ''' 取得對應資料來源的資料列索引。
        ''' </summary>
        ''' <param name="RowIndex">GridView 的資料列索引。</param>
        Public Function GetDataRowIndex(ByVal RowIndex As Integer) As Integer
            Dim iRowIndex As Integer

            If Me.AllowPaging Then
                'GridView 有分頁時,要把考慮目前的頁數及每頁筆數
                iRowIndex = Me.PageIndex * Me.PageSize + RowIndex
            Else
                'GridView 無分頁時,直接使用 RowIndex
                iRowIndex = RowIndex
            End If
            Return iRowIndex
        End Function

        ''' <summary>
        ''' 覆寫。引發 Load 事件。
        ''' </summary>
        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            MyBase.OnLoad(e)
            If Me.FormView IsNot Nothing Then
                If TypeOf Me.FormView Is TBFormView Then
                    DirectCast(Me.FormView, TBFormView).GridView = Me
                End If
            End If
        End Sub

        ''' <summary>
        ''' 覆寫。引發 RowCommand 事件。
        ''' </summary>
        Protected Overrides Sub OnRowCommand(ByVal e As GridViewCommandEventArgs)
            Dim iDataRowIndex As Integer

            Select Case e.CommandName.ToUpper
                Case "Edit".ToUpper '編輯模式
                    If Me.FormView IsNot Nothing Then
                        iDataRowIndex = GetDataRowIndex(CInt(e.CommandArgument))
                        Me.FormView.PageIndex = iDataRowIndex
                        Me.FormView.ChangeMode(FormViewMode.Edit) 'FormView 切換為編輯模式
                        Me.FormView.Visible = True  'FormView 顯示
                        Me.Visible = False 'GridView 隱藏
                    End If

                Case "Insert".ToUpper '新增模式
                    If Me.FormView IsNot Nothing Then
                        Me.FormView.ChangeMode(FormViewMode.Insert) 'FormView 切換為新增模式
                        Me.FormView.Visible = True  'FormView 顯示
                        Me.Visible = False 'GridView 隱藏
                    End If
            End Select
            MyBase.OnRowCommand(e)
        End Sub

    End Class
End Namespace

 

擴充 FormView 控制項

接下來繼承 FormView 下來擴充功能,首先要新增一個 GridView 屬性,當 TBGridView 有設定 FormViewID 時,且 FormView 的型別為 TBFormView 時,會去設定 TBFormView.GridView 屬性,讓 TBFormView 控制項知道繫結來源的 GridView,以做後序的相關程式控管。

TBFormView 的程式碼如下,一樣把原本 FormView 相關事件的程式碼搬過來控制項的程式碼中。

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Drawing
Imports Bee.Lib.TBLibFunc

Namespace WebControls
    ''' <summary>
    ''' 利用使用者定義的樣板,顯示資料來源中單一資料錄的值。支援編輯、刪除及插入資料錄。 
    ''' </summary>
    < _
    Description("TBFormView 控制項"), _
    ToolboxData("<{0}:TBFormView runat=server></{0}:TBFormView>") _
    > _
    Public Class TBFormView
        Inherits FormView
        Private FGridView As GridView = Nothing

        ''' <summary>
        ''' 連結的 GridView 控制項。
        ''' </summary>
        Protected Friend Property GridView() As GridView
            Get
                Return FGridView
            End Get
            Set(ByVal value As GridView)
                FGridView = value
            End Set
        End Property

        ''' <summary>
        ''' 遞迴尋找指定 ID 的控制項。
        ''' </summary>
        ''' <param name="Parent">父代控制項。</param>
        ''' <param name="CommandName">按鈕命令名稱。</param>
        ''' <returns>回傳 ID 符合的控制項,若未找到則傳回 Nothing。</returns>
        Private Overloads Function FindButtonControl(ByVal Parent As System.Web.UI.Control, ByVal CommandName As String) As IButtonControl
            Dim oControl As System.Web.UI.Control = Nothing
            Dim oButtonControl As IButtonControl = Nothing

            For Each oControl In Parent.Controls
                If (TypeOf oControl Is IButtonControl) Then
                    oButtonControl = DirectCast(oControl, IButtonControl)
                    If SameText(CommandName, oButtonControl.CommandName) Then
                        Return oButtonControl
                    End If
                Else
                    If oControl.Controls.Count > 0 Then
                        oButtonControl = FindButtonControl(oControl, CommandName)
                        If oButtonControl IsNot Nothing Then
                            Return oButtonControl
                        End If
                    End If
                End If
            Next

            Return Nothing
        End Function

        ''' <summary>
        ''' 依 CommandName 尋找對應的按鈕。
        ''' </summary>
        ''' <param name="CommandName">按鈕命令名稱。</param>
        Private Overloads Function FindButtonControl(ByVal CommandName As String) As IButtonControl
            Return FindButtonControl(Me, CommandName)
        End Function

        ''' <summary>
        ''' 覆寫。引發 Load 事件。
        ''' </summary>
        Protected Overrides Sub OnLoad(ByVal e As EventArgs)
            '若預設為編輯模式,則將 InsertItemTemplate 設為 EditItemTemplate
            If Me.DefaultMode = FormViewMode.Edit Then
                Me.InsertItemTemplate = Me.EditItemTemplate
            End If
            MyBase.OnLoad(e)
        End Sub

        ''' <summary>
        ''' 覆寫。引發 PreRender 事件。
        ''' </summary>
        Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
            Dim oButtonControl As IButtonControl

            MyBase.OnPreRender(e)

            If Me.Visible AndAlso Me.GridView IsNot Nothing Then
                Select Case Me.CurrentMode
                    Case FormViewMode.Edit '編輯模式
                        '隱藏新增鈕
                        oButtonControl = FindButtonControl("Insert")
                        If oButtonControl IsNot Nothing Then
                            DirectCast(oButtonControl, Control).Visible = False
                        End If
                        '顯示更新鈕
                        oButtonControl = FindButtonControl("Update")
                        If oButtonControl IsNot Nothing Then
                            DirectCast(oButtonControl, Control).Visible = True
                        End If
                    Case FormViewMode.Insert
                        '顯示新增鈕
                        oButtonControl = FindButtonControl("Insert")
                        If oButtonControl IsNot Nothing Then
                            DirectCast(oButtonControl, Control).Visible = True
                        End If
                        '隱藏更新鈕
                        oButtonControl = FindButtonControl("Update")
                        If oButtonControl IsNot Nothing Then
                            DirectCast(oButtonControl, Control).Visible = False
                        End If
                End Select
            End If
        End Sub

        ''' <summary>
        ''' 切換為瀏覽模式。
        ''' </summary>
        Private Sub ChangeViewMode()
            Me.Visible = False
            Me.GridView.Visible = True
            Me.GridView.EditIndex = -1
        End Sub

        ''' <summary>
        ''' 覆寫。引發 ItemInserted 事件。
        ''' </summary>
        Protected Overrides Sub OnItemInserted(ByVal e As FormViewInsertedEventArgs)
            MyBase.OnItemInserted(e)
            '切換為瀏覽模式
            ChangeViewMode()
        End Sub

        ''' <summary>
        ''' 覆寫。引發 ItemUpdated 事件。
        ''' </summary>
        Protected Overrides Sub OnItemUpdated(ByVal e As FormViewUpdatedEventArgs)
            MyBase.OnItemUpdated(e)
            '切換為瀏覽模式
            ChangeViewMode()
        End Sub

        ''' <summary>
        ''' 覆寫。引發 ItemCommand 事件。
        ''' </summary>
        Protected Overrides Sub OnItemCommand(ByVal e As FormViewCommandEventArgs)
            MyBase.OnItemCommand(e)
        End Sub
    End Class

End Namespace

 

使用 TBGridView 及 TBFormView 控制項

以上篇的範例程式做修改,只要將 aspx 中 GridView 置換為 TBGridView,而 FormView 置換為 TBFormView,並設定 TBGridView 的 FormViewID 屬性為 TBFormView 控制項 ID 即可。

<bee:TBGridView ID="GridView1" runat="server" AllowPaging="True" AutoGenerateColumns="False"
    CellPadding="4" DataKeyNames="EmployeeID" DataSourceID="SqlDataSource1" EmptyDataText="沒有資料錄可顯示。"
    ForeColor="#333333" GridLines="None" PageSize="5" FormViewID="FormView1">

而 aspx.vb 的程式碼可以簡化如下,原本 GridView 及 FormView 相關操作的控管都可以省略掉。

Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
        Dim oButton As Button

        If e.Row.RowType = DataControlRowType.DataRow Then
            '設定編輯鈕的 CommandArgument
            oButton = CType(e.Row.Cells(0).FindControl("btnEdit"), Button)
            oButton.CommandArgument = e.Row.RowIndex.ToString
        End If
    End Sub

    Protected Sub FormView1_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles FormView1.PreRender
        Dim oFormView As FormView
        Dim oTextBox As TextBox

        oFormView = CType(sender, FormView)
        If Not oFormView.Visible Then Exit Sub

        Select Case oFormView.CurrentMode
            Case FormViewMode.Edit '編輯模式
                '顯示 EmployeeID 的 TextBox
                oTextBox = oFormView.FindControl("txtEmployeeID")
                oTextBox.Visible = False
            Case FormViewMode.Insert
                '顯示 EmployeeID 的 TextBox
                oTextBox = oFormView.FindControl("txtEmployeeID")
                oTextBox.Visible = True
        End Select
    End Sub
End Class

 

後記

也許有人會問,可不可以連上述的程式碼都省略了,答案也是肯定的,只要去擴充 CommandField 及 TextBox 控制項就可以達到零程式碼。對於 CommandField 的部分,要讓 CommandField 的 Header 有辨法放「新增」鈕;而 TextBox 的部分,要讓 TextBox 有辨法自行判斷所在的 FormView 的 CurrentMode,自行決定本身是否要顯示或隱藏。

ASP.NET 魔法學院