C# 在DataGridView custon列中处理单元格解析
我为DataGridView定义了一个自定义列,以十六进制显示值。它所做的只是格式化文本并指定字体 (由于VB.NET中的历史原因:-)) 为了处理输入,我在网格上为CellParsing事件定义了一个处理程序C# 在DataGridView custon列中处理单元格解析,c#,.net,vb.net,winforms,datagridview,C#,.net,Vb.net,Winforms,Datagridview,我为DataGridView定义了一个自定义列,以十六进制显示值。它所做的只是格式化文本并指定字体 (由于VB.NET中的历史原因:-)) 为了处理输入,我在网格上为CellParsing事件定义了一个处理程序 Private Sub dgvValues_CellParsing(sender As Object, e As DataGridViewCellParsingEventArgs) Handles dgvValues.CellParsing If dgvValues.Col
Private Sub dgvValues_CellParsing(sender As Object, e As DataGridViewCellParsingEventArgs) Handles dgvValues.CellParsing
If dgvValues.Columns(e.ColumnIndex).Name = "NewDAC" _
OrElse dgvValues.Columns(e.ColumnIndex).Name = "NewOffset" _
OrElse dgvValues.Columns(e.ColumnIndex).Name = "New80PercentValue" _
Then
If e IsNot Nothing AndAlso e.Value IsNot Nothing Then
Try
Dim InputString As String = TryCast(e.Value, String)
Dim newValue As Int32 = TypeDescriptor.GetConverter(newValue).ConvertFrom(InputString)
Dim bytes As Byte() = BitConverter.GetBytes(newValue)
If e.DesiredType.Equals(GetType(UInt16)) Then
e.Value = BitConverter.ToUInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int16)) Then
e.Value = BitConverter.ToInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(UInt32)) Then
e.Value = BitConverter.ToUInt32 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int32)) Then
e.Value = newValue
End If
e.ParsingApplied = True
Catch
End Try
End If
End If
End Sub
这基本上是可行的,但我更愿意将单元解析逻辑完全封装在自定义列中
这样我就可以只选择列类型,一切都可以正常工作,而不需要在包含网格的表单中进行任何特殊处理
Private Sub dgvValues_CellParsing(sender As Object, e As DataGridViewCellParsingEventArgs) Handles dgvValues.CellParsing
If dgvValues.Columns(e.ColumnIndex).Name = "NewDAC" _
OrElse dgvValues.Columns(e.ColumnIndex).Name = "NewOffset" _
OrElse dgvValues.Columns(e.ColumnIndex).Name = "New80PercentValue" _
Then
If e IsNot Nothing AndAlso e.Value IsNot Nothing Then
Try
Dim InputString As String = TryCast(e.Value, String)
Dim newValue As Int32 = TypeDescriptor.GetConverter(newValue).ConvertFrom(InputString)
Dim bytes As Byte() = BitConverter.GetBytes(newValue)
If e.DesiredType.Equals(GetType(UInt16)) Then
e.Value = BitConverter.ToUInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int16)) Then
e.Value = BitConverter.ToInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(UInt32)) Then
e.Value = BitConverter.ToUInt32 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int32)) Then
e.Value = newValue
End If
e.ParsingApplied = True
Catch
End Try
End If
End If
End Sub
有没有办法在自定义列(或单元格)类中处理单元格解析?如果我正确理解了您的要求,
您需要在自定义列类中封装处理程序逻辑?。这样做是可行的,把sub放在类中,这样你的类应该看起来像这样
Public Class clsDgvHexColumn
Inherits DataGridViewTextBoxColumn
Private mFont As System.Drawing.Font
public sub New
MyBase.CellTemplate = new clsDgvHexColumnCell
mFont = New System.Drawing.Font ( "Consolas", 10 )
End Sub
Public Property Font As Font
Get
Return mFont
End Get
Set(ByVal value As Font)
mFont = value
Me.DefaultCellStyle.Font = mFont
End Set
End Property
Public Shared Sub Handler_CellParsing(sender As Object, e As DataGridViewCellParsingEventArgs)
Dim dgv as Your_Type //This is the type of dgvValues (which is DataGridView) I suppose, Replace Your_Type appropriately
dgv = CType(sender,Your_Type)
If dgv.Columns(e.ColumnIndex).Name = "NewDAC" _
OrElse dgv.Columns(e.ColumnIndex).Name = "NewOffset" _
OrElse dgv.Columns(e.ColumnIndex).Name = "New80PercentValue" _
Then
If e IsNot Nothing AndAlso e.Value IsNot Nothing Then
Try
Dim InputString As String = TryCast(e.Value, String)
Dim newValue As Int32 = TypeDescriptor.GetConverter(newValue).ConvertFrom(InputString)
Dim bytes As Byte() = BitConverter.GetBytes(newValue)
If e.DesiredType.Equals(GetType(UInt16)) Then
e.Value = BitConverter.ToUInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int16)) Then
e.Value = BitConverter.ToInt16 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(UInt32)) Then
e.Value = BitConverter.ToUInt32 ( bytes, 0 )
ElseIf e.DesiredType.Equals(GetType(Int32)) Then
e.Value = newValue
End If
e.ParsingApplied = True
Catch
End Try
End If
End If
End Sub
End Class
当您创建DataGridView或其他任何东西时,只需将事件处理程序添加到控件中,如下所示
AddHandler dgvValues.CellParsing , AddressOf clsDgvHexColumn.Handler_CellParsing
但是,我对您的目标的解释可能是错误的。根据Ivan Stoev的建议,这是我新的自定义列定义:
Public Class clsDgvHexColumn
Inherits DataGridViewTextBoxColumn
Private mFont As System.Drawing.Font
public sub New
MyBase.CellTemplate = new clsDgvHexColumnCell
mFont = New System.Drawing.Font ( "Consolas", 10 )
End Sub
Public Property Font As Font
Get
Return mFont
End Get
Set(ByVal value As Font)
mFont = value
Me.DefaultCellStyle.Font = mFont
End Set
End Property
End Class
Public Class clsDgvHexColumnCell
Inherits DataGridViewTextBoxCell
Protected Overrides Function GetFormattedValue ( ByVal value As Object, _
ByVal rowIndex As Integer, _
ByRef cellStyle As System.Windows.Forms.DataGridViewCellStyle, _
ByVal valueTypeConverter As System.ComponentModel.TypeConverter, _
ByVal formattedValueTypeConverter As System.ComponentModel.TypeConverter, _
ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts ) As Object
Return String.Format ( "0x{0:X4}", value )
End Function
Public Overrides Function ParseFormattedValue ( ByVal formattedValue As Object,
ByVal cellStyle As DataGridViewCellStyle,
ByVal formattedValueTypeConverter As TypeConverter,
ByVal valueTypeConverter As TypeConverter ) As Object
Dim InputString As String = TryCast(formattedValue, String)
Dim newValue As Int32 = TypeDescriptor.GetConverter(newValue).ConvertFrom(InputString)
Dim bytes As Byte() = BitConverter.GetBytes(newValue)
If ValueType.Equals(GetType(UInt16)) Then
Return BitConverter.ToUInt16 ( bytes, 0 )
ElseIf ValueType.Equals(GetType(Int16)) Then
Return BitConverter.ToInt16 ( bytes, 0 )
ElseIf ValueType.Equals(GetType(UInt32)) Then
Return BitConverter.ToUInt32 ( bytes, 0 )
ElseIf ValueType.Equals(GetType(Int32)) Then
Return newValue
Else
Return newValue
End If
End Function
End Class
目前,这似乎符合我的要求。我认为这就是解决方案。有没有办法获取绑定数据的类型(Int16、UInt16、Int32、UInt32)?如果没有,我可能会创建单独的列类型,HexColumnInt16、HexColumnUInt16、HexColumnInt32和HexColumnUInt32。属性(至少这是默认实现使用的:)谢谢,这很有效。如果我可以在自定义列类的代码中放置AddHandler调用,那就可以了。我必须想一想在哪里做这件事。此外,列检查还必须检查自身(而不是特定的命名列)。我想要的是选择列的类型,并且不需要表单中的其他自定义代码。