摘要
在「让 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 的定义转换为字段值。
在「让 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 的定义转换为字段值。
1
Imports System.Collections.Specialized
2
Imports System.ComponentModel
3
Imports System.Web
4
Imports System.Web.UI
5
Imports System.Web.UI.WebControls
6
7
Namespace 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 String, ByRef TrueValue As String, ByRef 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 Object) As 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 Boolean) As 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 Object, ByVal 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 > 0) Then
139
oControl = Cell.Controls.Item(0)
140
Dim oCheckBox As CheckBox = TryCast(oControl, CheckBox)
141
If ((Not oCheckBox Is Nothing) AndAlso (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 Nothing) Then
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
160
End Namespace
Imports System.Collections.Specialized2
Imports System.ComponentModel3
Imports System.Web4
Imports System.Web.UI5
Imports System.Web.UI.WebControls6

7
Namespace WebControls8
< _9
Description("复选框字段") _10
> _11
Public Class TBCheckBoxField12
Inherits CheckBoxField13

14
Private FDefineValue As String = String.Empty15

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 String24
Get25
Return FDefineValue26
End Get27
Set(ByVal value As String)28
FDefineValue = value29
End Set30
End Property31

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 String, ByRef TrueValue As String, ByRef FalseValue As String)39
Dim oParts() As String40

41
oParts = Split(Me.DefineValue, "/")42
If oParts.Length <> 2 Then43
Throw New HttpException("DefineValue 格式错误")44
End If45
TrueValue = oParts(0)46
FalseValue = oParts(1)47
End Sub48

49
''' <summary>50
''' 字段值依 DefineValue 的定义转换为布尔值。51
''' </summary>52
''' <param name="Value">字段值。</param>53
Private Function ValueToBoolean(ByVal Value As Object) As Boolean54
Dim sFieldValue As String55
Dim sTrueValue As String56
Dim sFalseValue As String57

58
sFieldValue = CStr(Value)59
sTrueValue = String.Empty60
sFalseValue = String.Empty61
ParserDefineValue(Me.DefineValue, sTrueValue, sFalseValue)62

63
If sFieldValue = sTrueValue Then64
Return True65
Else66
Return False67
End If68
End Function69

70
''' <summary>71
''' 布尔值依 DefineValue 的定义转换为字段值。72
''' </summary>73
''' <param name="Value">布尔值。</param>74
Private Function BooleanToValue(ByVal Value As Boolean) As Object75
Dim sTrueValue As String76
Dim sFalseValue As String77

78
sTrueValue = String.Empty79
sFalseValue = String.Empty80
ParserDefineValue(Me.DefineValue, sTrueValue, sFalseValue)81

82
If Value Then83
Return sTrueValue84
Else85
Return sFalseValue86
End If87
End Function88

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 Object, ByVal e As EventArgs)96
Dim oControl As Control = DirectCast(sender, Control)97
Dim oNamingContainer As Control = oControl.NamingContainer98
Dim oFieldValue As Object = Me.GetValue(oNamingContainer)99

100
If Not TypeOf oControl Is CheckBox Then101
Throw New HttpException("系结的控件非复选框")102
End If103

104
If IsDBNull(oFieldValue) Then105
DirectCast(oControl, CheckBox).Checked = False106
ElseIf TypeOf oFieldValue Is Boolean Then107
DirectCast(oControl, CheckBox).Checked = CBool(oFieldValue)108
Else109
If Not Me.DesignMode Then110
Try111
If Me.DefineValue <> String.Empty Then112
DirectCast(oControl, CheckBox).Checked = ValueToBoolean(oFieldValue)113
Else114
DirectCast(oControl, CheckBox).Checked = CBool(oFieldValue)115
End If116
Catch exception As FormatException117
Throw New HttpException("无法将值转为布尔值", exception)118
End Try119
End If120
End If121

122
DirectCast(oControl, CheckBox).Text = Me.Text123
End Sub124

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 = Nothing135
Dim sDataField As String = Me.DataField136
Dim oFieldValue As Object = Nothing137

138
If (Cell.Controls.Count > 0) Then139
oControl = Cell.Controls.Item(0)140
Dim oCheckBox As CheckBox = TryCast(oControl, CheckBox)141
If ((Not oCheckBox Is Nothing) AndAlso (IncludeReadOnly OrElse oCheckBox.Enabled)) Then142
If Me.DefineValue = String.Empty Then143
oFieldValue = oCheckBox.Checked144
Else145
oFieldValue = BooleanToValue(oCheckBox.Checked)146
End If147
End If148
End If149

150
If (Not oFieldValue Is Nothing) Then151
If Dictionary.Contains(sDataField) Then152
Dictionary.Item(sDataField) = oFieldValue153
Else154
Dictionary.Add(sDataField, oFieldValue)155
End If156
End If157
End Sub158

159
End Class160
End Namespace测试程序
我们使用 Northwind 数据库的 Employees 数据表做测试,在 Employees 加入一个 Checked 字段,数据型别为 nvarchar(1),字段值为 "是" 或 "否";我们使用 TBCheckBoxField 来系结 Checked 字段做测试。
我们分别使用 BoundField 及 TBCheckBoxField 同时系结 Checked 字段,BoundField 为只读供显示对照使用,而 TBCheckBoxField 则提供编辑 Checked 字段值,其中设定 TBCheckBoxField.DefineValue="是/否"。
执行程序,浏览数据的画面如下。
![]()
按下「编辑」钮进入编辑状态,使用 TBCheckBoxField 来编辑 Checked 字段。
![]()
按下「更新」钮后,会发现 Checked 字段值被正常更新了。
![]()

浙公网安备 33010602011771号