在 GridView+FormView 示范数据 新增/修改/删除(进阶篇:服务器控件) 一文中,示范了扩展 GridView 及 FormView 控件,让 GridView 可以透过属性与 FormView 做关连来处理数据的「新增/修改/删除」的动作。因为在该案例中,只使用 FormView 的 EditTemplate 同时处理「新增」及「修改」的动作,所以还需要自行撰写部分程序代码去判断控件在新增或修改的启用状态,例如编号字段在新增时为启用,修改时就不启用。在该文最后也提及其实有辨法让这个案例达到零程序代码的目标,那就是让控件 (如 TextBox) 自行判断所在的 FormView 的 CurrentMode,自行决定本身是否要「启用/不启用」、「显示/隐藏」等状态。本文以 TextBox 为例,说明如何修改 TextBox 让它可以达到上述的需求。
程序代码下载:ASP.NET Server Control - Day27.rar
Northwnd 数据库下载:NORTHWND.rar
一、TBFormViewModeState 类别
我们先定义 EControlState (控件状态) 列举,描述控件在特定模式的状态为何。
''' <summary>
''' 控制項狀態列舉。
''' </summary>
Public Enum EControlState
''' <summary>
''' 不設定。
''' </summary>
NotSet = 0
''' <summary>
''' 啟用。
''' </summary>
Enable = 1
''' <summary>
''' 不啟用。
''' </summary>
Disable = 2
''' <summary>
''' 隱藏。
''' </summary>
Hide = 3
End Enum
再来定义 TBFormViewModeState 类别,用来设定控件在各种 FormView 模式 (浏览、新增、修改) 中的控件状态。
''' <summary>
''' 依 FormViewMode 來設定控制項狀態。
''' </summary>
< _
Serializable(), _
TypeConverter(GetType(ExpandableObjectConverter)) _
> _
Public Class TBFormViewModeState
Private FInsertMode As EControlState = EControlState.NotSet
Private FEditMode As EControlState = EControlState.NotSet
Private FBrowseMode As EControlState = EControlState.NotSet
''' <summary>
''' 在新增模式(FormViewMode=Insert)的控制項狀態。
''' </summary>
< _
NotifyParentProperty(True), _
DefaultValue(GetType(EControlState), "NotSet") _
> _
Public Property InsertMode() As EControlState
Get
Return FInsertMode
End Get
Set(ByVal value As EControlState)
FInsertMode = value
End Set
End Property
''' <summary>
''' 在編輯模式(FormViewMode=Edit)的控制項狀態。
''' </summary>
< _
NotifyParentProperty(True), _
DefaultValue(GetType(EControlState), "NotSet") _
> _
Public Property EditMode() As EControlState
Get
Return FEditMode
End Get
Set(ByVal value As EControlState)
FEditMode = value
End Set
End Property
''' <summary>
''' 在瀏覽模式(FormViewMode=ReadOnly)的控制項狀態。
''' </summary>
< _
NotifyParentProperty(True), _
DefaultValue(GetType(EControlState), "NotSet") _
> _
Public Property BrowseMode() As EControlState
Get
Return FBrowseMode
End Get
Set(ByVal value As EControlState)
FBrowseMode = value
End Set
End Property
End Class
定义为 TBFormViewModeState 型别的属性是属于复杂属性,要套用 TypeConverter(GetType(ExpandableObjectConverter)),让该属性可在属性窗口 (PropertyGrid) 扩展以便设定属性值,如下图所示。
二、让 TextBox 控件可自行维护状态
接下来扩展 TextBox 控件,继承 TextBox 命名为 TBTextBox。新增 FormViewModeState 属性 (TBFormViewModeState 型别),依 FormView Mode 来设定控件状。并覆写 PreRender 方法,在此方法中呼叫 DoFormViewModeStatus 私有方法,依 FormView 的模式来处理控件状态。
''' <summary>
''' 文字框控制項。
''' </summary>
< _
Description("文字框控制項。"), _
ToolboxData("<{0}:TBTextBox runat=server></{0}:TBTextBox>") _
> _
Public Class TBTextBox
Inherits TextBox
Private FFormViewModeState As TBFormViewModeState
''' <summary>
''' 依 FormViewMode 來設定控制項狀態。
''' </summary>
< _
Description("依 FormViewMode 來設定控制項狀態。"), _
Category(WebCommon.Category.Behavior), _
NotifyParentProperty(True), _
DesignerSerializationVisibility(DesignerSerializationVisibility.Content), _
PersistenceMode(PersistenceMode.InnerProperty), _
DefaultValue("") _
> _
Public ReadOnly Property FormViewModeState() As TBFormViewModeState
Get
If FFormViewModeState Is Nothing Then
FFormViewModeState = New TBFormViewModeState
End If
Return FFormViewModeState
End Get
End Property
''' <summary>
''' 處理控制項狀態。
''' </summary>
''' <param name="ControlStatus">控制項狀態。</param>
Private Sub DoControlStatus(ByVal ControlStatus As EControlState)
Select Case ControlStatus
Case EControlState.Enable
Me.Enabled = True
Case EControlState.Disable
Me.Enabled = False
Case EControlState.Hide
Me.Visible = False
End Select
End Sub
''' <summary>
''' 依 FormView 的模式來處理控制項狀態。
''' </summary>
Private Sub DoFormViewModeStatus()
Dim oFormView As FormView
'若控制項置於 FormView 中,則依 FormView 的模式來處理控制項狀態
If TypeOf Me.BindingContainer Is FormView Then
oFormView = DirectCast(Me.BindingContainer, FormView)
Select Case oFormView.CurrentMode
Case FormViewMode.Insert
DoControlStatus(Me.FormViewModeState.InsertMode)
Case FormViewMode.Edit
DoControlStatus(Me.FormViewModeState.EditMode)
Case FormViewMode.ReadOnly
DoControlStatus(Me.FormViewModeState.BrowseMode)
End Select
End If
End Sub
''' <summary>
''' 覆寫。引發 PreRender 事件。
''' </summary>
Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
MyBase.OnPreRender(e)
'依 FormView 的模式來處理控制項狀態
DoFormViewModeStatus()
End Sub
End Class
三、测试程序
1. 设定控件相关属性
我们使用 Northwnd 数据库的 Products数据表为例,以 GridView+FormView 示范数据「新增/修改/删除」的操作。在页面拖曳 SqlDataSource 控件后,在页面上的使用 TBGridView 来显示浏览数据。TBGridView 的 FormViewID 设为关连的 TBFormVIew 控件;另外有使用到 TBCommandField,设定 ShowHeaderNewButton=True,让命令列具有「新增」钮。
<bee:TBGridView ID="TBGridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="SqlDataSource1" CellPadding="4" ForeColor="#333333"
GridLines="None" AllowPaging="True" FormViewID="TBFormView1">
<RowStyle BackColor="#EFF3FB" />
<Columns>
<bee:TBCommandField ShowDeleteButton="True" ShowEditButton="True"
ShowHeaderNewButton="True" >
</bee:TBCommandField>
'省略
</Columns>
</bee:TBGridView>
接下来设定做为新增、编辑使用的 TBFormView 控件,我们只使用 EditItemTemplate 来同时处理新增、删除,所以 EditItemTemplate 需要同时具有「新增」、「更新」、「取消」三个按钮。其中 ProductID 为主索引字段,所以我们使用 TBTextBox 来系结 ProductID 字段,设定 FormViewModeState.InsertMode="Enable" 使控件在新增模式时为可编辑,设定 FormViewModeState.EditMode="Disable" 使控件在修改模式是只读的。
<bee:TBFormView ID="TBFormView1" runat="server" DataKeyNames="ProductID" DataSourceID="SqlDataSource1"
DefaultMode="Edit" SingleTemplate="EditItemTemplate" BackColor="White" BorderColor="#CCCCCC"
BorderStyle="None" BorderWidth="1px" CellPadding="3" GridLines="Both" Visible="False">
<FooterStyle BackColor="White" ForeColor="#000066" />
<RowStyle ForeColor="#000066" />
<EditItemTemplate>
ProductID:
<bee:TBTextBox ID="TextBox1" runat="server" Text='<%# Bind("ProductID") %>'>
<FormViewModeState EditMode="Disable" InsertMode="Enable">
</FormViewModeState>
</bee:TBTextBox>
'省略
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True" CommandName="Insert"
Text="新增" />
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="更新" />
<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False"
CommandName="Cancel" Text="取消" />
</EditItemTemplate>
</bee:TBFormView>
2. 测试新增模式
接下来执行程序,一开始为浏览模式,以 TBGridView 来呈现数据。
按下 Header 的「新增」钮,就会隐藏 TBGridView,而切换到 TBFormView 的新增模式。其中系结 ProductID 字段的 TBTextBox 为可编辑模式,而下方的按钮只会显示「新增」及「取消」钮。
在新增模式输入完毕后,按下「新增」钮,数据录就会被写入数据库。
3. 测试修改模式
接下来测试修改模式,按下「编辑」钮,就会隐藏 TBGridView,而切换到 TBFormView 的修改模式。其中系结 ProductID 字段的 TBTextBox 为只读模式,而下方的按钮只会显示「更新」及「取消」钮。
在修改模式输入完毕后,按下「更新」钮,数据录就会被写入数据库。
4. 页面程序代码
示范了上述的操作后,接下来我们回头看一下页面的程序代码。你没看错,笔者也没贴错,真的是一行程序代码都没有,因为所有相关动作都由控件处理掉了。
Partial Class Day27
Inherits System.Web.UI.Page
End Class
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10013233
http://ithelp.ithome.com.tw/question/10013239
http://ithelp.ithome.com.tw/question/10013241