Square Filled CheckBox in Datagridview

2019-07-07 05:17发布

问题:

I have a Database that looks like this

Table Name : ri_closure

as what you see on the image above all of the columns except Month are TinyInt(1) and Month is Varchar now I have a code here

 Dim con1 As MySqlConnection = New MySqlConnection("server=192.168.2.87;userid=root;password=admin1950;database=inventory")
        Dim sql1 As MySqlCommand = New MySqlCommand("Select * from ri_closure", con1)
        Dim ds1 As DataSet = New DataSet
        Dim adapter1 As MySqlDataAdapter = New MySqlDataAdapter
        con1.Open()
        adapter1.SelectCommand = sql1
        adapter1.Fill(ds1, "MyTable")
        DataGridView2.DataSource = ds1.Tables(0)
        con1.Close()
        ds1.Tables(0).Columns(2).DataType = GetType(Boolean)
        Me.DataGridView2.Columns(1).Frozen = True
        Dim i As Integer
        For i = 0 To DataGridView2.Columns.Count - 1
            DataGridView2.Columns.Item(i).SortMode = DataGridViewColumnSortMode.Programmatic
        Next
        DataGridView2.Columns(0).Visible = False
        DataGridView2.Columns(1).DefaultCellStyle.BackColor = Color.LightBlue

Now this is what it looks like

Now you see the output and I'm sure you dont that want that red ones. Irritating in the eyes and here is my code for that

  For Each rw As DataGridViewRow In DataGridView2.Rows
            For ii As Integer = 2 To rw.Cells.Count - 1
                If rw.Cells(ii).Value = False Then
                    rw.Cells(ii).Style.BackColor = Color.Red
                ElseIf rw.Cells(ii).Value = True Then
                    rw.Cells(ii).Style.BackColor = Color.White
                End If
            Next
        Next

Now here is my question and I hope it is possible. I want to do something like this instead uncked and turn the cell in to red How can I make the uncked cell like this.

instead of empty checkbox it will look the same as the image above.

and another one I hope the that will generate filled checkbox will replace the uncheked value because I have code in checking of that one.

I try some code and this is the output

TYSM for future help

回答1:

You can customize painting of DataGridViewCheckBox column by handling CellPainting event of DataGridView. Then you can use CheckBoxRenderer to draw the check box in desired state. The state which you want to show for unchecked state of check box is CheckBoxState.MixedNormal:

Private Sub CellPainting(ByVal sender As Object, _
    ByVal e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
    If (e.ColumnIndex = 0 AndAlso e.RowIndex >= 0) Then
        Dim value = DirectCast(e.FormattedValue, Nullable(Of Boolean))
        e.Paint(e.CellBounds, DataGridViewPaintParts.All And _
                              Not (DataGridViewPaintParts.ContentForeground))
        Dim state = IIf((value.HasValue And value.Value), _
                        VisualStyles.CheckBoxState.CheckedNormal, _
                        VisualStyles.CheckBoxState.MixedNormal)
        Dim size = RadioButtonRenderer.GetGlyphSize(e.Graphics, state)
        Dim location = New Point((e.CellBounds.Width - size.Width) / 2, _
                                (e.CellBounds.Height - size.Height) / 2)
        location.Offset(e.CellBounds.Location)
        CheckBoxRenderer.DrawCheckBox(e.Graphics, location, state)
        e.Handled = True
    End If
End Sub

To test the solution you can add a column to grid this way:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load
    Dim C1 = New DataGridViewCheckBoxColumn()
    C1.DataPropertyName = "C1"
    C1.HeaderText = "C1"
    C1.TrueValue = 1
    C1.FalseValue = 0
    Me.DataGridView1.Columns.Add(C1)
    Me.DataGridView1.Rows.Add(DirectCast(1, Object))
    Me.DataGridView1.Rows.Add(DirectCast(0, Object))
    Me.DataGridView1.AllowUserToAddRows = False
End Sub

And this will be the result:

To draw the unchecked (in fact mixed state) in red color, after calling CheckBoxRenderer.DrawCheckBox use this code:

If (state = VisualStyles.CheckBoxState.MixedNormal) Then
    Dim rect = New Rectangle(location, size)
    rect.Inflate(-2, -2)
    e.Graphics.FillRectangle(Brushes.Red, rect)
End If



回答2:

You can utilize the DataGridView's VirtualMode and then use CellValueNeeded event to display your own content.

Here is what I suggest you should do,

  1. Decide an image to be displayed instead of checkbox (example a green tick)
  2. Set the DataGridView's VirtualMode property to true
  3. After binding the DataGridView with your DataTable iterate through all month columns set the DataProperptyName as empty string (this important in order to trigger the event)
  4. Create an event handler for DataGridView's CellValueNeeded event, in this event you will be receiving the Column Index and Row Index in event parameters. Use that to find the actual value behind and then return the green tick image (using e.Value) or return a blank image depending on the value.