首页 > 解决方案 > 如何在 DataGridView 的选定单元格中添加和删除 FontStyle

问题描述

我有一个 DataGridView,其中某些单元格包含 2 或 3 位数字到 3 位小数,例如 47.231。
我需要能够将其中一些单元格的字体样式更改为FontStyle.Strikeout,最好使用 keydown (不是CtrlAlt)并单击一个单元格。

稍后,通过一个按钮事件,我将在最右侧添加一行中单元格的值的总和。
总和不应包括带有删除线的单元格的值。
我不知道如何开始,但是一篇稍微相关的帖子使用代码来更改包含某些单词的所有单元格。请参阅下面的代码。

For Each r As DataGridViewRow In frmCheckOut_Room.DataGridView2.Rows
Dim cell As DataGridViewCell = r.Cells(9)
If cell.Value = "Void" Then
    cell.Style.ForeColor = Color.Red
    cell.Font = New Font("Microsoft Sans Serif", 8, FontStyle.Strikeout)
ElseIf cell.Value = "Active" Then
    cell.Style.Font = New Font("Microsoft Sans Serif", 8)
    cell.Style.BackColor = Color.Orange
End If
Next

标签: vb.netwinformsdatagridview

解决方案


试试这个。
您可以使用 ALT + 鼠标左键或按键(此处已处理)来切换FontStyle.Strikeout包含原始值(不是由计算生成的值)的任何单元格。 这些组合可以存储在配置文件中。Keys.S

注意:如果您不想使用键修饰符,则必须将 DataGridView 的EditMode设置为DataGridViewEditMode.EditOnF2or DataGridViewEditMode.EditProgrammatically,否则不会引发 KeyDown 事件并且当前单元格将始终进入编辑模式。
由于EditProgrammatically增加了复杂性(您需要处理很多情况,否则会引发异常),我将其设置为EditOnF2(因此,您需要按F2进入编辑模式)。如果您改为选择 Key 修饰符 + Key(例如Control + K),则可以保留默认值EditMode.

有一种评估当前字体样式的方法:

Private Function GetCellFont(cell As DataGridViewCell) As Font
    Return If(IsNothing(cell.Style.Font), cell.InheritedStyle.Font, cell.Style.Font)
End Function

因为 Cell 可能没有自己的字体集。它可以被继承。在这种情况下,[DataGridViewCell].Style.Font为 null ( nothing)。

在 Form 的构造函数中订阅 DataGridView 事件,或者在绑定 DataSource 之前订阅:

AddHandler DataGridView1.CellFormatting, AddressOf dgv_CellFormatting
AddHandler DataGridView1.CellMouseDown, AddressOf dgv_CellMouseDown
AddHandler DataGridView1.CellValueChanged, AddressOf dgv_CellValueChanged
AddHandler DataGridView1.KeyDown, AddressOf dgv_KeyDown

在示例代码中(我添加了一个动画,以便设置更清晰),前三列保存十进制值,后两列显示StrikeOut未设置样式的所有行单元格的总和和平均值。
Average 列只是为了显示使用decimal.Round()来确定要考虑的小数位数。

切换单元格的字体样式或更改值时,会更新相应的计算值(第 3 列和第 4 列)。

由编辑单元格引起的值更改由CellValueChanged事件处理,调用 Form 的Validate()方法,这会导致 DataGridView 格式化具有Dirty状态的单元格。


DataGridView 字体切换

Private Sub dgv_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs)
    If (e.RowIndex < 0) OrElse (e.ColumnIndex < 3) Then Return
    Dim value As Decimal = CalculateValues(e.ColumnIndex, e.RowIndex, DirectCast(sender, DataGridView))
    e.Value = value
End Sub

Private Sub dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs)
    If e.ColumnIndex > 2 Then Return
    Validate()
End Sub

Private Sub dgv_CellMouseDown(sender As Object, e As DataGridViewCellMouseEventArgs)
    If (e.RowIndex < 0) OrElse ((e.ColumnIndex < 0) OrElse (e.ColumnIndex > 2)) Then Return
    If (ModifierKeys <> Keys.Alt) OrElse (e.Button <> MouseButtons.Left) Then Return
    Dim dgv = DirectCast(sender, DataGridView)
    ToggleCellFontStyle(dgv(e.ColumnIndex, e.RowIndex))
End Sub

Private Sub dgv_KeyDown(sender As Object, e As KeyEventArgs)
    Dim currentCell As DataGridViewCell = DirectCast(sender, DataGridView).CurrentCell
    If e.KeyValue = Keys.S AndAlso currentCell IsNot Nothing Then
        e.SuppressKeyPress = True
        If (currentCell.ColumnIndex < 0) OrElse (currentCell.ColumnIndex > 2) Then Return
        ToggleCellFontStyle(DataGridView1.CurrentCell)
    End If
End Sub

Private Function CalculateValues(columnIndex As Integer, rowIndex As Integer, dgv As DataGridView) As Decimal
    Dim sum As Decimal = 0.0D
    Dim avg As Decimal = 0.0D
    Dim valuesCounted As Integer = 0

    For col As Integer = 0 To 2
        Dim fStyle = GetCellFont(dgv(col, rowIndex)).Style And FontStyle.Strikeout
        If fStyle <> FontStyle.Strikeout Then
            valuesCounted += 1
            Dim cellValue = dgv(col, rowIndex).Value
            sum += CDec(If(cellValue Is DBNull.Value, 0.00D, cellValue))
        End If
    Next
    avg = Decimal.Round(If(valuesCounted > 0, sum / valuesCounted, 0.00D), 3)
    Return If(columnIndex = 3, sum, avg)
End Function

Private Sub ToggleCellFontStyle(cell As DataGridViewCell)

    Dim cellFont As Font = GetCellFont(cell)
    Dim cellFontStyle As FontStyle = cellFont.Style
    Dim isStrikeOut = (cellFontStyle And FontStyle.Strikeout) = FontStyle.Strikeout

    cellFontStyle = If(isStrikeOut, cellFontStyle Xor FontStyle.Strikeout, cellFontStyle Or FontStyle.Strikeout)
    cell.Style.Font?.Dispose()
    cell.Style.Font = New Font(cellFont, cellFontStyle)
End Sub

Private Function GetCellFont(cell As DataGridViewCell) As Font
    Return If(IsNothing(cell.Style.Font), cell.InheritedStyle.Font, cell.Style.Font)
End Function

推荐阅读