Imports System
Imports System.Windows.Forms
''' <summary>
''' DataGridViewMaskedTextBoxCellオブジェクトの列を表します。
''' 用于DataGridView中MaskedTextBoxCell的列。
''' </summary>
Public Class DataGridViewMaskedTextBoxColumn
Inherits DataGridViewColumn
'CellTemplateとするDataGridViewMaskedTextBoxCellオブジェクトを指定して
'使用DataGridViewMaskedTextBoxCell对象调用基类构造函数
Public Sub New()
MyBase.New(New DataGridViewMaskedTextBoxCell())
End Sub
Private maskValue As String = ""
Private promptValue As String = ""
Private maskFormatValue As System.Windows.Forms.MaskFormat
''' <summary>
''' 要应用于MaskedTextBox的Mask属性的值,即格式
''' </summary>
Public Property Mask() As String
Get
Return Me.maskValue
End Get
Set(ByVal value As String)
Me.maskValue = value
End Set
End Property
''' <summary>
''' 要应用于MaskedTextBox的PromptChar属性的值
''' </summary>
''' <returns></returns>
Public Property Prompt() As String
Get
Return Me.promptValue
End Get
Set(ByVal value As String)
Me.promptValue = value
End Set
End Property
''' <summary>
''' 要应用于MaskedTextBox的MaskFormat
''' </summary>
''' <returns></returns>
Public Property MaskFormat() As String
Get
Return Me.maskFormatValue
End Get
Set(ByVal value As String)
Me.maskFormatValue = value
End Set
End Property
'由于我们添加了新属性,因此我们需要重写克隆方法。
Public Overrides Function Clone() As Object
Dim col As DataGridViewMaskedTextBoxColumn =
DirectCast(MyBase.Clone(), DataGridViewMaskedTextBoxColumn)
col.Mask = Me.Mask
col.Prompt = Me.Prompt
col.MaskFormat = Me.MaskFormat
Return col
End Function
'获取和设置CellTemplate
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
'DataGridViewMaskedTextBoxCellしかCellTemplateに設定できないようにする
'DataGridViewMaskedTextBoxCell只能设定为CellTemplate
If Not (TypeOf value Is DataGridViewMaskedTextBoxCell) Then
Throw New InvalidCastException("指定DataGridViewMaskedTextBoxCell对象。")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
''' <summary>
''' 在DataGridView控件中显示可在MaskedTextBox中编辑的文本信息。
''' </summary>
Public Class DataGridViewMaskedTextBoxCell
Inherits DataGridViewTextBoxCell
'构造函数
Public Sub New()
End Sub
'初始化编辑控件
'编辑控件也用于其他单元格和列,因此需要初始化
Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer,
ByVal initialFormattedValue As Object,
ByVal dataGridViewCellStyle As DataGridViewCellStyle)
MyBase.InitializeEditingControl(rowIndex, initialFormattedValue,
dataGridViewCellStyle)
'获取编辑控件
Dim maskedBox As DataGridViewMaskedTextBoxEditingControl =
TryCast(Me.DataGridView.EditingControl,
DataGridViewMaskedTextBoxEditingControl)
If maskedBox IsNot Nothing Then
'设置Text
Dim maskedText As String = TryCast(initialFormattedValue, String)
maskedBox.Text = If(maskedText IsNot Nothing, maskedText, " : : ")
'反映自定义列的属性
Dim column As DataGridViewMaskedTextBoxColumn =
TryCast(Me.OwningColumn, DataGridViewMaskedTextBoxColumn)
If column IsNot Nothing Then
maskedBox.Mask = column.Mask
maskedBox.PromptChar = column.Prompt
maskedBox.TextMaskFormat=column.MaskFormat
End If
End If
End Sub
'指定编辑控件的类型
Public Overrides ReadOnly Property EditType() As Type
Get
Return GetType(DataGridViewMaskedTextBoxEditingControl)
End Get
End Property
'指定单元格值的数据类型
'在此,设为Object与基类相同,无需重写
Public Overrides ReadOnly Property ValueType() As Type
Get
Return GetType(Object)
End Get
End Property
'为新记录行中的单元格指定默认值
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
Return MyBase.DefaultNewRowValue
End Get
End Property
End Class
''' <summary>
''' 表示由DataGridViewMaskedTextBoxCell托管的MaskedTextBox。
''' </summary>
Public Class DataGridViewMaskedTextBoxEditingControl
Inherits MaskedTextBox
Implements IDataGridViewEditingControl
'显示编辑控件的DataGridView
Private dataGridView As DataGridView
'显示编辑控件的行
Private rowIndex As Integer
'编辑控件的值是否与单元格的值不同
Private valueChanged As Boolean
'构造函数
Public Sub New()
Me.TabStop = False
End Sub
#Region "IDataGridViewEditingControl メンバ"
'编辑控件中已更改的单元格的值
Public Function GetEditingControlFormattedValue(
ByVal context As DataGridViewDataErrorContexts) As Object _
Implements IDataGridViewEditingControl.GetEditingControlFormattedValue
Return Me.Text
End Function
'编辑控件中已更改的单元格的值
Public Property EditingControlFormattedValue() As Object _
Implements IDataGridViewEditingControl.EditingControlFormattedValue
Get
Return Me.GetEditingControlFormattedValue(
DataGridViewDataErrorContexts.Formatting)
End Get
Set(ByVal value As Object)
Me.Text = DirectCast(value, String)
End Set
End Property
'将单元格样式应用于编辑控件 (前景颜色、背景颜色、字体对齐)
Public Sub ApplyCellStyleToEditingControl(
ByVal dataGridViewCellStyle As DataGridViewCellStyle) _
Implements IDataGridViewEditingControl.ApplyCellStyleToEditingControl
Me.Font = dataGridViewCellStyle.Font
Me.ForeColor = dataGridViewCellStyle.ForeColor
Me.BackColor = dataGridViewCellStyle.BackColor
Select Case dataGridViewCellStyle.Alignment
Case DataGridViewContentAlignment.BottomCenter,
DataGridViewContentAlignment.MiddleCenter,
DataGridViewContentAlignment.TopCenter
Me.TextAlign = HorizontalAlignment.Center
Exit Select
Case DataGridViewContentAlignment.BottomRight,
DataGridViewContentAlignment.MiddleRight,
DataGridViewContentAlignment.TopRight
Me.TextAlign = HorizontalAlignment.Right
Exit Select
Case Else
Me.TextAlign = HorizontalAlignment.Left
Exit Select
End Select
End Sub
'包含要编辑的单元格的DataGridView
Public Property EditingControlDataGridView() As DataGridView _
Implements IDataGridViewEditingControl.EditingControlDataGridView
Get
Return Me.dataGridView
End Get
Set(ByVal value As DataGridView)
Me.dataGridView = value
End Set
End Property
'正在编辑的行的索引
Public Property EditingControlRowIndex() As Integer _
Implements IDataGridViewEditingControl.EditingControlRowIndex
Get
Return Me.rowIndex
End Get
Set(ByVal value As Integer)
Me.rowIndex = value
End Set
End Property
'值是否已更改
'编辑控件的值和单元格的值是否不同
Public Property EditingControlValueChanged() As Boolean _
Implements IDataGridViewEditingControl.EditingControlValueChanged
Get
Return Me.valueChanged
End Get
Set(ByVal value As Boolean)
Me.valueChanged = value
End Set
End Property
'指定されたキーをDataGridViewが処理するか、編集コントロールが処理するか
Public Function EditingControlWantsInputKey(ByVal keyData As Keys,
ByVal dataGridViewWantsInputKey As Boolean) As Boolean _
Implements IDataGridViewEditingControl.EditingControlWantsInputKey
'Keys.Left、Right、Home、End时返回 True;如果不这样做, 这些键会将焦点转移到另一个单元格
Select Case keyData And Keys.KeyCode
Case Keys.Right, Keys.[End], Keys.Left, Keys.Home
Return True
Case Else
Return Not dataGridViewWantsInputKey
End Select
End Function
'指定鼠标光标位于“EditingPanel”上时的光标
'“EditingPanel”是承载编辑控件的面板。
'如果编辑控件小于单元格,则控件以外的部分将成为panel
Public ReadOnly Property EditingPanelCursor() As Cursor _
Implements IDataGridViewEditingControl.EditingPanelCursor
Get
Return MyBase.Cursor
End Get
End Property
'准备在控件中编辑
'选择文本或结束插入符号
Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) _
Implements IDataGridViewEditingControl.PrepareEditingControlForEdit
If selectAll Then
'进入选择状态
Me.SelectAll()
Else
'在字节结尾插入符号
Me.SelectionStart = Me.TextLength
End If
End Sub
'如果值更改,则是否更改单元格位置;如果值更改,需要更改编辑控件大小,则为 True。
Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean _
Implements IDataGridViewEditingControl.RepositionEditingControlOnValueChange
Get
Return False
End Get
End Property
#End Region
'当值更改时
Protected Overrides Sub OnTextChanged(ByVal e As EventArgs)
MyBase.OnTextChanged(e)
'通知DataGridView值已更改
Me.valueChanged = True
Me.dataGridView.NotifyCurrentCellDirty(True)
End Sub
'当在输入框按了键时,判断是否是数字,然后更改值
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
MyBase.OnKeyDown(e)
'在掩码块判断
If e.KeyCode = Keys.Tab Then
'Dim pos As Integer = Me.SelectionStart
'Dim max As Integer = (Me.MaskedTextProvider.Length - Me.MaskedTextProvider.EditPositionCount)
'Dim nextField As Integer = 0
'For i As Integer = 0 To Me.MaskedTextProvider.Length - 1
' If Not Me.MaskedTextProvider.IsEditPosition(i) AndAlso (pos + max) >= i Then nextField = i
'Next
'nextField += 1
''完成,开启TabStop
'If pos = nextField Then Key_Leave(Me, e)
'Me.SelectionStart = nextField
ElseIf e.KeyCode = Keys.Enter Then
ElseIf (e.KeyCode >= Keys.D0 And e.KeyCode <= Keys.D9) Or
(e.KeyCode >= Keys.NumPad0 And e.KeyCode <= Keys.NumPad9) Then
Dim pos As Integer = Me.SelectionStart
'从指定位置开始向前第一个未赋值可编辑的位置,填满了返回-1
Dim PosNextUnassignedMask = Me.MaskedTextProvider.FindUnassignedEditPositionFrom(pos, True)
'从指定位置开始向前第一个不可编辑的位置
Dim PosNextNonEdit = Me.MaskedTextProvider.FindNonEditPositionFrom(pos, True)
'得到输入的值并判断输入的值是0-9的哪个,并转换成Char
Dim str = If(((e.KeyValue - Keys.NumPad0) < 0) And (e.KeyValue >= Keys.D0 And e.KeyValue <= Keys.NumPad9),
CChar((e.KeyValue - Keys.D0).ToString),
DirectCast(CChar((e.KeyValue - Keys.NumPad0).ToString), Object))
'已经填满了字符串的话,输入变成插入(把光标后一个字符替换了,只能替换最近掩码前的)
If PosNextUnassignedMask < 0 Then
'光标在掩码前,则更改下一个掩码区第一个可编辑的位置
If (PosNextNonEdit = pos) Then
Dim tmp = Me.Text.ToCharArray
tmp(pos + 1) = str
Dim tmp2 As String = ""
For i = 0 To tmp.Length - 1
tmp2 = tmp2 & tmp(i)
Next
Me.Text = tmp2
Me.SelectionStart = pos + 2
'这个改不了值
'Me.MaskedTextProvider.Replace(str, PosNextNonEdit + 1)
'Me.MaskedTextProvider.InsertAt(str, PosNextNonEdit + 1)
Else
Dim tmp = Me.Text.ToCharArray
tmp(pos) = str
Dim tmp2 As String = ""
For i = 0 To tmp.Length - 1
tmp2 = tmp2 & tmp(i)
Next
Me.Text = tmp2
Me.SelectionStart = pos + 1
End If
End If
End If
End Sub
End Class