摘要
在「让 CheckBoxField 系结非布尔值(0 或 1)字段」一文中有介绍了如何修改 CheckFieldBox 去系结 0 或 1 的非布尔值,其作法是将非布尔直接使用 CBool 函式将字段值强制转型为布尔值。 不过有时系结的字段值并无法直接使用 CBool 转型为布尔值,例如 "T/F"、"是/否" 之类的资料,若希望使用 CheckBoxField 来显示就比较麻烦,一般的作法都是转为 TemplateField,自行撰写数据系结的函式,而且只能支持单向系结。在本文中我们将直接改写 CheckBoxField 类别,让 CheckBoxField 可以直接双向系结 "T/F" 或 "是/否" 之类的资料。

扩展 CheckBoxField 类别
我们继承 CheckBoxField 命名为 TBCheckBoxField,新增 DefineValue 属性,用来做布尔值转换定义(格式为 "True/False");若设定 DefineValue="是/否",即字段值为 "是" 对应到 True,而 "否" 对应到 False。
当读取字段值要系结至控件时会引发 OnDataBindField 方法;故覆写 OnDataBindField 方法,判断若有设定  DefineValue 属性,则利用 ValueToBoolean 方法将字段值依 DefineValue 的定义转换为布尔值。例如将 "男/女" 转为 "True/False",再与控件做系结。
当要写入数据时会由控件撷取出目前的字段值,此时会引发 ExtractValuesFromCell 方法;故覆写 ExtractValuesFromCell 方法,此时会撷取 CheckBoxField 内含的 CheckBox 控件的 Checked 属性值(布尔值),若有设定 DefineValue 属性时,会利用 BooleanToValue 方法将布尔值依 DefineValue 的定义转换为字段值。
  1Imports System.Collections.Specialized
  2Imports System.ComponentModel
  3Imports System.Web
  4Imports System.Web.UI
  5Imports System.Web.UI.WebControls
  6
  7Namespace WebControls
  8    < _
  9    Description("复选框字段") _
 10    > _
 11    Public Class TBCheckBoxField
 12        Inherits CheckBoxField
 13
 14        Private FDefineValue As String = String.Empty
 15
 16        ''' <summary>
 17        ''' 布尔值转换定义,格式为 "True/False"。
 18        ''' </summary>
 19        ''' <returns>
 20        ''' 当设定为 "T/F" 时,表示 T 为 True,F 为 False。
 21        ''' 当设定为 "T/*" 时,表示 T 为 True,其它为 False。
 22        ''' </returns> 

 23        Public Property DefineValue() As String
 24            Get
 25                Return FDefineValue
 26            End Get
 27            Set(ByVal value As String)
 28                FDefineValue = value
 29            End Set
 30        End Property

 31
 32        ''' <summary>
 33        ''' 解析布尔值转换定义。
 34        ''' </summary>
 35        ''' <param name="DefineValue">布尔值转换定义。</param>
 36        ''' <param name="TrueValue">True 的对应值。</param>
 37        ''' <param name="FalseValue">False 的对应值。</param>

 38        Private Sub ParserDefineValue(ByVal DefineValue As StringByRef TrueValue As StringByRef FalseValue As String)
 39            Dim oParts() As String
 40
 41            oParts = Split(Me.DefineValue, "/")
 42            If oParts.Length <> 2 Then
 43                Throw New HttpException("DefineValue 格式错误")
 44            End If
 45            TrueValue = oParts(0)
 46            FalseValue = oParts(1)
 47        End Sub

 48
 49        ''' <summary>
 50        ''' 字段值依 DefineValue 的定义转换为布尔值。
 51        ''' </summary>
 52        ''' <param name="Value">字段值。</param>

 53        Private Function ValueToBoolean(ByVal Value As ObjectAs Boolean
 54            Dim sFieldValue As String
 55            Dim sTrueValue As String
 56            Dim sFalseValue As String
 57
 58            sFieldValue = CStr(Value)
 59            sTrueValue = String.Empty
 60            sFalseValue = String.Empty
 61            ParserDefineValue(Me.DefineValue, sTrueValue, sFalseValue)
 62
 63            If sFieldValue = sTrueValue Then
 64                Return True
 65            Else
 66                Return False
 67            End If
 68        End Function

 69
 70        ''' <summary>
 71        ''' 布尔值依 DefineValue 的定义转换为字段值。
 72        ''' </summary>
 73        ''' <param name="Value">布尔值。</param>

 74        Private Function BooleanToValue(ByVal Value As BooleanAs Object
 75            Dim sTrueValue As String
 76            Dim sFalseValue As String
 77
 78            sTrueValue = String.Empty
 79            sFalseValue = String.Empty
 80            ParserDefineValue(Me.DefineValue, sTrueValue, sFalseValue)
 81
 82            If Value Then
 83                Return sTrueValue
 84            Else
 85                Return sFalseValue
 86            End If
 87        End Function

 88
 89
 90        ''' <summary>
 91        ''' 将字段值系结至 TBCheckBoxField 对象中的复选框。 
 92        ''' </summary>
 93        ''' <param name="sender">作用的控件。</param>
 94        ''' <param name="e">事件自变量。</param>

 95        Protected Overrides Sub OnDataBindField(ByVal sender As ObjectByVal e As EventArgs)
 96            Dim oControl As Control = DirectCast(sender, Control)
 97            Dim oNamingContainer As Control = oControl.NamingContainer
 98            Dim oFieldValue As Object = Me.GetValue(oNamingContainer)
 99
100            If Not TypeOf oControl Is CheckBox Then
101                Throw New HttpException("系结的控件非复选框")
102            End If
103
104            If IsDBNull(oFieldValue) Then
105                DirectCast(oControl, CheckBox).Checked = False
106            ElseIf TypeOf oFieldValue Is Boolean Then
107                DirectCast(oControl, CheckBox).Checked = CBool(oFieldValue)
108            Else
109                If Not Me.DesignMode Then
110                    Try
111                        If Me.DefineValue <> String.Empty Then
112                            DirectCast(oControl, CheckBox).Checked = ValueToBoolean(oFieldValue)
113                        Else
114                            DirectCast(oControl, CheckBox).Checked = CBool(oFieldValue)
115                        End If
116                    Catch exception As FormatException
117                        Throw New HttpException("无法将值转为布尔值", exception)
118                    End Try
119                End If
120            End If
121
122            DirectCast(oControl, CheckBox).Text = Me.Text
123        End Sub

124
125        ''' <summary>
126        ''' 使用指定 DataControlFieldCell 对象的值填入指定的 System.Collections.IDictionary 物件。 
127        ''' </summary>
128        ''' <param name="dictionary">用于储存指定储存格的值。</param>
129        ''' <param name="cell">包含要撷取值的储存格。</param>
130        ''' <param name="rowState">数据列的状态。</param>
131        ''' <param name="includeReadOnly">true 表示包含只读字段的值,否则为 false。</param>

132        Public Overrides Sub ExtractValuesFromCell(ByVal Dictionary As IOrderedDictionary, ByVal Cell As DataControlFieldCell, _
133            ByVal RowState As DataControlRowState, ByVal IncludeReadOnly As Boolean)
134            Dim oControl As Control = Nothing
135            Dim sDataField As String = Me.DataField
136            Dim oFieldValue As Object = Nothing
137
138            If (Cell.Controls.Count > 0Then
139                oControl = Cell.Controls.Item(0)
140                Dim oCheckBox As CheckBox = TryCast(oControl, CheckBox)
141                If ((Not oCheckBox Is NothingAndAlso (IncludeReadOnly OrElse oCheckBox.Enabled)) Then
142                    If Me.DefineValue = String.Empty Then
143                        oFieldValue = oCheckBox.Checked
144                    Else
145                        oFieldValue = BooleanToValue(oCheckBox.Checked)
146                    End If
147                End If
148            End If
149
150            If (Not oFieldValue Is NothingThen
151                If Dictionary.Contains(sDataField) Then
152                    Dictionary.Item(sDataField) = oFieldValue
153                Else
154                    Dictionary.Add(sDataField, oFieldValue)
155                End If
156            End If
157        End Sub

158
159    End Class

160End Namespace

测试程序
我们使用 Northwind 数据库的 Employees 数据表做测试,在 Employees 加入一个 Checked 字段,数据型别为 nvarchar(1),字段值为 "是" 或 "否";我们使用 TBCheckBoxField 来系结 Checked 字段做测试。
我们分别使用 BoundField 及 TBCheckBoxField 同时系结 Checked 字段,BoundField 为只读供显示对照使用,而 TBCheckBoxField 则提供编辑 Checked 字段值,其中设定 TBCheckBoxField.DefineValue="是/否"。

执行程序,浏览数据的画面如下。

按下「编辑」钮进入编辑状态,使用 TBCheckBoxField 来编辑 Checked 字段。

按下「更新」钮后,会发现 Checked 字段值被正常更新了。

posted on 2008-05-21 19:54  jeff377  阅读(2690)  评论(0编辑  收藏  举报