I've got multiple radio buttons and want to paint them based on a variable.
The base code I've found here: Changing 'lamp' Colour Indicator within the Graphical User Interface (Visual Studio 2019)
Now this one works for 1 radiobutton, but as I stated, I've multiple.
My code looks:
Private Sub cbStart_CheckedChanged(sender As Object, e As EventArgs) Handles cbStartEDD.CheckedChanged
rbEDD.ForeColor = Color.White
rbEDD.ForeColor = Color.Black
rbCV.ForeColor = Color.White
rbCV.ForeColor = Color.Black
End Sub
Private Sub rbEDD_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles rbEDD.Paint, rbCV
If cbStart = -1 Then
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(1, 1, 10, 10))
Else If cbStart =0 then
e.Graphics.FillEllipse(Brushes.Orange, New RectangleF(1, 1, 10, 10))
Else
e.Graphics.FillEllipse(Brushes.Green, New RectangleF(1, 1, 10, 10))
End If
End Sub
So, when I change/click the checkbox, all radio buttons.
What I can do is: a sub for every radiobutton:
Private Sub cbStart_CheckedChanged(sender As Object, e As EventArgs) Handles cbStartEDD.CheckedChanged
rbEDD.ForeColor = Color.White
rbEDD.ForeColor = Color.Black
rbCV.ForeColor = Color.White
rbCV.ForeColor = Color.Black
End Sub
Private Sub rbEDD_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles rbEDD.Paint
If cbSV = -1 Then
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(1, 1, 10, 10))
Else If cbSV =0 then
e.Graphics.FillEllipse(Brushes.Orange, New RectangleF(1, 1, 10, 10))
Else
e.Graphics.FillEllipse(Brushes.Green, New RectangleF(1, 1, 10, 10))
End If
End Sub
Private Sub rbCV_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles rbCV.Paint
If cbCV = -1 Then
e.Graphics.FillEllipse(Brushes.Red, New RectangleF(1, 1, 10, 10))
Else If cbStart =0 then
e.Graphics.FillEllipse(Brushes.Orange, New RectangleF(1, 1, 10, 10))
Else
e.Graphics.FillEllipse(Brushes.Green, New RectangleF(1, 1, 10, 10))
End If
End Sub
And what I want is one sub that when it is called that changes the color of the radiobutton variable: following code is just describing what I want to have:
Private Sub cb<Name of the checkbox>_CheckedChanged(sender As Object, e As EventArgs) Handles cb<Name of the checkbox>.CheckedChanged
Call buttoncolor(<name of the radiobutton>, <statusvalue(-1,0 or 1)>)
End Sub
Private Sub buttoncolor(radiobutton As Object, status As Integer)
If status = -1 Then
' do following to the radiobutton object
radiobutton.e.Graphics.FillEllipse(Brushes.Red, New RectangleF(1, 1, 10, 10))
Else If status = 0 then
radiobutton.e.Graphics.FillEllipse(Brushes.Orange, New RectangleF(1, 1, 10, 10))
Else
radiobutton.e.Graphics.FillEllipse(Brushes.Green, New RectangleF(1, 1, 10, 10))
End If
End Sub
Is there an easy way to do it or do I have to copy&paste the Paint-sub many times?
You need to keep the graphics in the Paint event because as you may have seen, you only have access to the graphics object there. You can access it elsewhere but the Paint event will override whatever you do outside of it. But you can make one handler for both RadioButtons' Paint events, note the Handles rbCV.Paint, rbEdd.Paint
Add a dictionary to maintain a relationship between RadioButtons and CheckBoxes
Private radioToCheck As New Dictionary(Of RadioButton, CheckBox)()
Private Sub Form_Load() Handles Me.Load
radioToCheck.Add(rbEdd, cbSV)
radioToCheck.Add(rbCV, cbCV)
End Sub
Then the Paint event can handle multiple RadioButtons' Paint events
Private Sub rb_Paint(sender As Object, e As PaintEventArgs) Handles rbCV.Paint, rbEdd.Paint
Dim b As Brush
Select Case radioToCheck(DirectCast(sender, RadioButton)).CheckState - 1
Case -1 : b = Brushes.Red
Case 0 : b = Brushes.Orange
Case Else : b = Brushes.Green
End Select
e.Graphics.FillEllipse(b, New RectangleF(1, 1, 10, 10))
End Sub
I took a liberty in determining how status comes from the CheckBox, because cbCV = -1
won't work - a CheckBox can't equal -1. I guess it's the CheckState - 1, as a CheckBox has three states {0, 1, 2} and your status are {-1, 0, 1}. If that's wrong, you can change the logic radioToCheck(rb).CheckState - 1
to a function to get the status given the CheckBox.
Ideally, the state is not stored in the UI, and you would use some model to represent the state and the UI is updated when the state changes, and is used to update the state. On a small scale, what you're doing is fine, but it will be very clumsy and the UI may become sluggish as you scale up.