GridView+FormView 示範資料 新增/修改/刪除(進階篇:伺服器控制項)
摘要
承上一篇文章「GridView+FormView 示範資料 新增/修改/刪除」,有人詢問是否能簡化程式碼;答案是可行的,方法就是由伺服器控制項下手。在此文章中,我們將擴充 GridView 及 FormView 控制項,在 GridView 控制項中新增 FormViewID 屬性,關連至指定的 FormView 控制項 ID,就可以輕易達到上篇文章中相同效果。
擴充 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,自行決定本身是否要顯示或隱藏。