【问题标题】:Handle cell parsing in DataGridView custon column处理 DataGridView 自定义列中的单元格解析
【发布时间】:2017-07-21 08:26:08
【问题描述】:

我为 DataGridView 定义了一个自定义列,以十六进制显示值。它所做的只是格式化文本并指定字体。

(由于 VB.NET 中的历史原因 :-))

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

End Class

为了处理输入,我为网格上的 CellParsing 事件定义了一个处理程序。

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

这基本上是可行的,但我更喜欢将单元格解析逻辑完全封装在自定义列中。

这样我可以只选择列类型,一切都会正常工作,而无需在包含网格的表单中进行任何特殊处理。

有没有办法在自定义列(或单元格)类中处理 CellParsing?

【问题讨论】:

  • 我认为这就是解决方案。有没有办法获取绑定数据的类型(Int16、UInt16、Int32、UInt32)?如果没有,我可能会创建单独的列类型,HexColumnInt16、HexColumnUInt16、HexColumnInt32 和 HexColumnUInt32。
  • ValueType 属性(至少这是默认实现使用的:)
  • 谢谢,这行得通。

标签: c# .net vb.net winforms datagridview


【解决方案1】:

根据 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

目前,这似乎是我想要的。

【讨论】:

    【解决方案2】:

    如果我正确理解了您的要求,You need to encapsulate the handler logic inside the custom column class?。然后这样的事情是可行的,将子放在类中,这样你的类应该看起来像这样

    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 或其他任何内容时,只需像这样将事件处理程序添加到 Control,

    AddHandler dgvValues.CellParsing , AddressOf clsDgvHexColumn.Handler_CellParsing
    

    但是,我对您的目标的解释可能是错误的。

    【讨论】:

    • 如果我可以将 AddHandler 调用放在自定义列类的代码中就可以了。我必须弄清楚在哪里做。此外,列检查必须检查自身(而不是特定的命名列)。我想要的是选择列的类型,并且不需要表单中的其他自定义代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多