2D Collision detection in Visual Basic - vb.net

This is my first time writing a small winform game. When researching into collision detection i know that i need to set my bounds first.
Me.Controls.Add(PlayerShip) 'imports the picture box onto the PlayScreen
PlayerShip.Width = 40
PlayerShip.Height = 40 'Dimensions of the player ship
PlayerShip.BorderStyle = BorderStyle.FixedSingle 'adds a border to the picturebox
PlayerShip.BackColor = Color.White 'adds colour to the ship background
PlayerShip.SetBounds(x:=40, y:=40, height:=40, width:=40)
And then the other picture box
Me.Controls.Add(WallNorth)
WallNorth.Width = 750
WallNorth.Height = 5
WallNorth.BorderStyle = BorderStyle.FixedSingle
WallNorth.BackColor = Color.Green
WallNorth.Top = 1
WallNorth.Left = 1
WallNorth.SetBounds(x:=1, y:=1, height:=5, width:=750)
Private Sub PlayScreen_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyValue
Case Keys.Right
MoveRight = True
Case Keys.Left
MoveLeft = True 'This edits the boolean value of the varibales when the correct key is pressed
Case Keys.Up
MoveUp = True
Case Keys.Down
MoveDown = True
End Select
End Sub
Private Sub PlayScreen_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyValue
Case Keys.Right
MoveRight = False
Case Keys.Left
MoveLeft = False 'This edits the boolean value when the key has been lifted
Case Keys.Up
MoveUp = False
Case Keys.Down
MoveDown = False
End Select
End Sub
Private Sub MovementTimer_Tick(sender As Object, e As EventArgs) Handles MovementTimer.Tick
If MoveRight = True Then
PlayerShip.Left += 5
End If
If MoveLeft = True Then
PlayerShip.Left -= 5
End If
If MoveUp = True Then
PlayerShip.Top -= 5 ' I use a timer to tick every 10 milliseconds ato check the states of each key, this statement controlls the execution of the direction
End If
If MoveDown = True Then
PlayerShip.Top += 5
End If
End Sub
End Class
However when i try to write an if statement to check if they will collide or not i do not get a '.bounds' option. I have seen '.bounds' being needed after the name of the picture box. Instead i have been met with '.setbounds' even though i have set them before.
Is something wrong with my version of visual studio, or am I missing something?

Related

Collision Detection edits the Spawn Location of a Picture Box

I am making a two dimensional game where the user is able to shoot enemies and gain points. So far I have added borders to the level as well as the collision detection between the Player and said borders. When the player presses "w" the user shoots a bullet. Without me setting the boundaries, the bullet appears at the centre of the players sprite. With the boundaries set, the bullets appear to increase height from the player when spawned; when the player moves to the left of the screen. Vice Versa when the player moves to the right.
The first Class:
Public Class Bullet
Inherits PictureBox 'this class is a variation of a picture box
Public Sub New() 'every time bullet is accessed it will access this sub as well
With Me 'refers back to anything in the class
.Height = 5
.Width = 2
.Location = PlayScreen.PlayerShip.Location 'sets the bullets start point to the ship
.BackColor = Color.White
.SetBounds(x:=PlayScreen.PlayerShip.Left, y:=PlayScreen.PlayerShip.Left, height:=5, width:=2)
End With
End Sub
Public Sub ShootUp()
Me.Top -= 10 'Males the bullet move upwards
End Sub
End Class
The Rest of my Code:
Public Class PlayScreen
Public Shared PlayerShip As New PictureBox 'defines the ship as a picture box
Dim WallNorth As New PictureBox
Dim WallSouth As New PictureBox
Dim WallEast As New PictureBox 'these will be given collision detection to check if the player is trying to exit the boundires of the level
Dim WallWest As New PictureBox
Dim Bullets(-1) As Bullet 'makes the array have nothing in it
Dim BulletCounter As Integer 'used to make new bullets
Dim MoveRight As Boolean = False
Dim MoveLeft As Boolean = False 'Making movement based upon boolean factors allows for more user friendly controls
Dim MoveUp As Boolean = False
Dim MoveDown As Boolean = False
Dim PUHealth As New PictureBox
Dim Health As Integer
Dim Score As Integer
Private Sub PlayScreen_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MovementTimer.Start()
PUHealthTimer.Start()
Health = 3
HealthLbl.Text = "Health: " & Health
Score = 0
ScoreLbl.Text = "Score: " & Score
Me.Controls.Add(PUHealth)
PUHealth.Width = 25
PUHealth.Height = 25
PUHealth.BorderStyle = BorderStyle.FixedSingle
PUHealth.BackColor = Color.Yellow
PUHealth.Top = Me.Height / 2 - 100
PUHealth.Left = Me.Width / 2 - 100
PUHealth.SetBounds(x:=Me.Height / 2 - 100, y:=Me.Width / 2 - 100, height:=25, width:=25)
Me.Controls.Add(PlayerShip) 'imports the picture box onto the PlayScreen
PlayerShip.Width = 40
PlayerShip.Height = 40 'Dimensions of the player ship
PlayerShip.BorderStyle = BorderStyle.FixedSingle 'adds a border to the picturebox
PlayerShip.BackColor = Color.White 'adds colour to the ship background
PlayerShip.SetBounds(x:=Me.Left, y:=Me.Top, height:=40, width:=40)
Me.Controls.Add(WallNorth)
WallNorth.Width = 750
WallNorth.Height = 5
WallNorth.BorderStyle = BorderStyle.FixedSingle 'this is defining the wall at the top of the screen, setting its positions as well as its bounds
WallNorth.BackColor = Color.Green
WallNorth.Top = 1
WallNorth.Left = 1
WallNorth.SetBounds(x:=1, y:=1, height:=5, width:=750)
Me.Controls.Add(WallEast)
WallEast.Width = 5
WallEast.Height = 750
WallEast.BorderStyle = BorderStyle.FixedSingle 'This defines the wall at the right of the screen, setting its position as well as its bounds
WallEast.BackColor = Color.Green
WallEast.Top = 1
WallEast.Left = 545
WallEast.SetBounds(x:=545, y:=1, width:=5, height:=750)
Me.Controls.Add(WallSouth)
WallSouth.Width = 750
WallSouth.Height = 5
WallSouth.BorderStyle = BorderStyle.FixedSingle
WallSouth.BackColor = Color.Green
WallSouth.Top = 574
WallSouth.Left = 1
WallSouth.SetBounds(x:=1, y:=573, width:=750, height:=5)
Me.Controls.Add(WallWest)
WallWest.Width = 5
WallWest.Height = 750
WallWest.BorderStyle = BorderStyle.FixedSingle
WallWest.BackColor = Color.Green
WallWest.Top = 1
WallWest.Left = 1
End Sub
Private Sub PlayScreen_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
Select Case e.KeyValue
Case Keys.Right
MoveRight = True
Case Keys.Left
MoveLeft = True 'This edits the boolean value of the varibales when the correct key is pressed
Case Keys.Up
MoveUp = True
Case Keys.Down
MoveDown = True
Case Keys.W
ReDim Preserve Bullets(BulletCounter) 'allows the array to expand more efficiently
Dim Bullet1 As New Bullet 'creates new bullet
Controls.Add(Bullet1) 'adds bullet to the screen
Bullets(BulletCounter) = Bullet1 'the new space created in the array is saved as the new bullet made
BulletCounter += 1
ShootUpTimer.Start() 'starts the shoot timer
End Select
While WallNorth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top += 5
End While
While WallEast.Bounds.IntersectsWith(PlayerShip.Bounds) 'I have to check if the player has collided with the wall when the key is down
PlayerShip.Left -= 5
End While
While WallSouth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top -= 5
End While
While WallWest.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Left += 5
End While
If PUHealth.Bounds.IntersectsWith(PlayerShip.Bounds) Then 'checks if the player has collided with the the power up
If PUHealth.Visible() Then 'This stops a bug where the player could go to the spot where the power up use to be and collect health
Health += 1 'increaeses the players health by one
HealthLbl.Text = "Health: " & Health 'displays the new player health
PUHealth.Hide() 'hides the power up
End If
End If
End Sub
Private Sub PlayScreen_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyValue
Case Keys.Right
MoveRight = False
Case Keys.Left
MoveLeft = False 'This edits the boolean value when the key has been lifted
Case Keys.Up
MoveUp = False
Case Keys.Down
MoveDown = False
End Select
While WallNorth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top += 5
End While
While WallEast.Bounds.IntersectsWith(PlayerShip.Bounds) 'i have to check if the player collides with a wall while the key is down
PlayerShip.Left -= 5
End While
While WallSouth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top -= 5
End While
If PUHealth.Bounds.IntersectsWith(PlayerShip.Bounds) Then
If PUHealth.Visible() Then
Health += 1
HealthLbl.Text = "Health: " & Health
PUHealth.Hide()
End If
End If
End Sub
Private Sub MovementTimer_Tick(sender As Object, e As EventArgs) Handles MovementTimer.Tick
If MoveRight = True Then
PlayerShip.Left += 5
End If
If MoveLeft = True Then
PlayerShip.Left -= 5
End If
If MoveUp = True Then
PlayerShip.Top -= 5 ' I use a timer to tick every 10 milliseconds ato check the states of each key, this statement controlls the execution of the direction
End If
If MoveDown = True Then
PlayerShip.Top += 5
End If
While WallNorth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top += 5
End While
While WallEast.Bounds.IntersectsWith(PlayerShip.Bounds) 'i check if the player is collided with the wall whilst the timer ticks because the player could not collide with the wall every 20 milliseconds
PlayerShip.Left -= 5
End While
While WallSouth.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Top -= 5
End While
While WallWest.Bounds.IntersectsWith(PlayerShip.Bounds)
PlayerShip.Left += 5
End While
If PUHealth.Bounds.IntersectsWith(PlayerShip.Bounds) Then
If PUHealth.Visible() Then
Health += 1
HealthLbl.Text = "Health: " & Health
PUHealth.Hide()
End If
End If
End Sub
Private Sub PUHealthTimer_Tick(sender As Object, e As EventArgs) Handles PUHealthTimer.Tick
If PUHealth.Visible() Then 'checks if the health power up i visible
Else 'if not the coordinates are randomised and then displayerd
PUHealth.Top = ((500 * Rnd()) + 10)
PUHealth.Left = ((500 * Rnd()) + 10)
PUHealth.Show()
End If
End Sub
Private Sub ShootTimerUp_Tick(sender As Object, e As EventArgs) Handles ShootUpTimer.Tick
For x = 0 To Bullets.Length - 1 'to check every position within the array apart from the newest
Bullets(x).ShootUp()
Next
End Sub
End Class
What do i need to change to get the bullets to shoot from the middle, of the top, of the ship.
In the Public Class I declared the X and Y location both as the x location

How do I set my picturebox (bullets in my case) on their own axis seperate from my character's movement in VB?

I'm very, VERY, new to coding and started a class in Visual Studio and the language Visual Basic in a .NET windows form app. So on that note, please cut me some slack.
I am trying to make a little game where you can move your character and shoot a monster or two in only 4 directions (left, right, up, left). Well, the problem is that my bullets move when I try to move my character with the WASD keys. This is most likely because I have set my WASD keys to both movements for the movement of the character, and the direction in which the bullets (PictureBox) shoots. I've tried making boolean switches, but me being new to coding seems to have caused some trouble figuring it out. I'll drop what I have so far:
Public Class Form1
Dim Health As Integer = 7
Dim UUp As Boolean = True
Dim UDown As Boolean = True
Dim ULeft As Boolean = True
Dim URight As Boolean = True
Dim EUp As Boolean = True
Dim EDown As Boolean = True
Dim ELeft As Boolean = True
Dim ERight As Boolean = True
Dim Bullets(-1) As Bullet
Dim intCount As Integer
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
'movement of character player controls
If (e.KeyCode = Keys.W And UUp = True) Then
pbIssac.Top -= 5
ElseIf (e.KeyCode = Keys.A And ULeft = True) Then
pbIssac.Left -= 5
ElseIf (e.KeyCode = Keys.D And URight = True) Then
pbIssac.Left += 5
ElseIf (e.KeyCode = Keys.S And UDown = True) Then
pbIssac.Top += 5
ElseIf (e.KeyCode = Keys.Escape) Then
End
End If
'creation of bullet? code from internet!
Select Case e.KeyCode
Case Keys.Space
ReDim Preserve Bullets(intCount)
Dim bullet1 As New Bullets
Controls.Add(bullet1)
Bullets(intCount) = bullet1
intCount += 1
tmrShoot.Enabled = True
End Select
'direction character is facing determines direction of bullet
If (e.KeyCode = Keys.A) Then
My.Settings.Keypressed = 1
My.Settings.Save()
ElseIf (e.KeyCode = Keys.D) Then
My.Settings.Keypressed = 2
My.Settings.Save()
ElseIf (e.KeyCode = Keys.W) Then
My.Settings.Keypressed = 3
My.Settings.Save()
ElseIf (e.KeyCode = Keys.S) Then
My.Settings.Keypressed = 4
My.Settings.Save()
End If
Bullet Class (From the internet!)
Public Class Bullet
Inherits PictureBox
Public Sub New()
With Me
.Size = New Size(10, 30)
.Location = Form1.pbIssac.Location
.BackgroundImageLayout = ImageLayout.Stretch
.BackgroundImage = My.Resources.green
End With
End Sub
Public Sub Shoot()
If (My.Settings.Keypressed = 1) Then
Me.Left -= 3
My.Settings.Save()
ElseIf (My.Settings.Keypressed = 2) Then
Me.Left += 3
My.Settings.Save()
ElseIf (My.Settings.Keypressed = 3) Then
Me.Top -= 3
My.Settings.Save()
ElseIf (My.Settings.Keypressed = 4) Then
Me.Top += 4
My.Settings.Save()
End If
End Sub
End Class
This is the sort of thing that I would do in that situation:
Public Class Form1
Private characterPosition As Point
'Set a default direction for the character.
Private characterDirection As Direction = Direction.Up
Private ReadOnly bullets As New List(Of Bullet)
Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Keys.W
characterDirection = Direction.Up
'Move character up.
Case Keys.S
characterDirection = Direction.Down
'Move character down.
Case Keys.A
characterDirection = Direction.Left
'Move character left.
Case Keys.D
characterDirection = Direction.Right
'Move character right.
Case Keys.Space
bullets.Add(New Bullet(characterPosition, characterDirection))
End Select
End Sub
End Class
Public Enum Direction
Up
Down
Left
Right
End Enum
Public Class Bullet
Private direction As Direction
Public Sub New(location As Point, direction As Direction)
'...
Me.direction = direction
End Sub
Public Sub Move()
Select Case direction
Case Direction.Up
'Move bullet up.
Case Direction.Down
'Move bullet down.
Case Direction.Left
'Move bullet left.
Case Direction.Right
'Move bullet right.
End Select
End Sub
End Class
Note that each bullet remembers its own direction so you just tell it to move and it moves.

Collision Issue Pinball VB.net 2015

So I am making a basic pinball game using vb.net and am having an issue with the collisions that once the ball slows down a certain amount it glitches inside and then through the walls.
I am using a picturebox for the walls and the ball and am using the intersectwith(picturebox command to detect collision.
any help on how to fix this would be appreciated. Thanks
Bellow is most of the code: (pctball is the ball)
Private Sub Screen_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DoubleBuffered = True
dX = 6 ' Pixels per timer tick
dY = 6
Timer1.Enabled = True
'array for colliding scores
For Each obj In Me.Controls
If TypeOf obj Is PictureBox AndAlso obj.tag = "Disc" Then
DiscArray(i) = obj
i += 1
End If
Next
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If GameActive = True Then
Labelx.Text = PctBall.Left
Labely.Text = PctBall.Top
PctBall.Left = PctBall.Left + dX
PctBall.Top = PctBall.Top + dY
' check for ball hitting edges, reverse direction if so
If PctBall.Left < 10 Or PctBall.Left > MyBase.Width - PctBall.Width Then
dX = -dX
End If
If PctBall.Top < 10 Then
dY = -dY
End If
If LeftFlipper = True Then
FlipperDefaultL.Visible = False
FlipperUpL.Visible = True
Else
FlipperDefaultL.Visible = True
FlipperUpL.Visible = False
End If
If RightFlipper = True Then
FlipperDefaultR.Visible = False
FlipperUpR.Visible = True
Else
FlipperDefaultR.Visible = True
FlipperUpR.Visible = False
End If
GravityFunction()
ReboundAngle()
' If ball goes outside bottom
If PctBall.Bottom > MyBase.Height Then
GameActive = False
Game_Over()
End If
End If
End Sub
Private Sub Keys_Down(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyValue
Case Keys.Space
GameActive = True
Case Keys.D
LeftFlipper = True
Case Keys.K
RightFlipper = True
End Select
End Sub
Private Sub Keys_Up(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Select Case e.KeyValue
'Case Keys.Space
' GameActive = False
Case Keys.D
LeftFlipper = False
Case Keys.K
RightFlipper = False
End Select
End Sub
Private Sub GravityFunction()
' gravity
gravity = CollisionCount
dY += gravity
PctBall.Top += dY
End Sub
Private Function CheckCollision()
For Each PictureBox In Me.Controls
If PictureBox IsNot PctBall AndAlso PictureBox.visible = True AndAlso PctBall.Bounds.IntersectsWith(PictureBox.Bounds) Then
collision = True
CollisionCount += 0.1
For discCount = 0 To DiscArray.Length - 1
If PictureBox IsNot PctBall AndAlso PctBall.Bounds.IntersectsWith(DiscArray(discCount).Bounds) Then
score = score + 1
ScoreBoard.scorelabel.Text = "Score: " & score
End If
Next
Exit For 'Exit when at least one collision found
Else : collision = False
End If
Next
If Collision = True Then
Coll.Text = "True"
Else
Coll.Text = "False"
End If
Return collision
End Function
Private Function ReboundAngle()
If CheckCollision() Then
dX = -dX
dY = -dY
End If
End Function

Move scrollbars automatically when doing a rectangle selection for cropping an image in the picture box with panel's Autoscroll = True

I have a picturebox on top of a panel..I have a rectangle selection which can be used to select a portion of the image for cropping..Since I have set the Panel's Autoscroll property = True, and since the image in picture box is big, I get the scroll bars. But for selecting a portion of image for cropping, I need to drag the rectangle beyond what is visible to me. I cannot do so when the mouse reaches the extreme right of the picturebox.. I would like to design it in a way that when mouse reaches the extreme right my scroll bars should automatically move right.. But with Autoscroll property I cannot get the scrollbar values. Any workaround available for this problem??
This probably works a little smoother with a Timer to move the AutoScrollPosition property:
Private horzMove As ArrowDirection = -1
Private vertMove As ArrowDirection = -1
Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
If e.Button = MouseButtons.Left Then
If Panel1.AutoScrollPosition.X + e.Location.X > Panel1.ClientSize.Width Then
horzMove = ArrowDirection.Right
ElseIf Panel1.AutoScrollPosition.X + e.Location.X < 0 Then
horzMove = ArrowDirection.Left
Else
horzMove = -1
End If
If Panel1.AutoScrollPosition.Y + e.Location.Y > Panel1.ClientSize.Height Then
vertMove = ArrowDirection.Down
ElseIf Panel1.AutoScrollPosition.Y + e.Location.Y < 0 Then
vertMove = ArrowDirection.Up
Else
vertMove = -1
End If
End If
End Sub
Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
horzMove = -1
vertMove = -1
End Sub
Make sure the timer is enabled:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If horzMove > -1 Or vertMove > -1 Then
Dim newLeft As Integer = -Panel1.AutoScrollPosition.X
Dim newTop As Integer = -Panel1.AutoScrollPosition.Y
Select Case horzMove
Case ArrowDirection.Left
newLeft = -Panel1.AutoScrollPosition.X - 32
Case ArrowDirection.Right
newLeft = -Panel1.AutoScrollPosition.X + 32
End Select
Select Case vertMove
Case ArrowDirection.Down
newTop = -Panel1.AutoScrollPosition.Y + 32
Case ArrowDirection.Up
newTop = -Panel1.AutoScrollPosition.Y - 32
End Select
Panel1.AutoScrollPosition = New Point(newLeft, newTop)
End If
End Sub

Mimic radiobuttons in datagridview using DataGridViewCheckBoxColumns

PLEASE NOTE: this question is about DataGridViewCheckBoxColumns inside a DataGridView control - not the normal CheckBox control.
I have a winforms app that contains a DataGridView with three checkbox (DataGridViewCheckBoxColumn) columns. I'd like to mimic radiobuttons ie. one, and only one, checkbox is checked at a time. I am able to turn off the other checkboxes in the grid when one is clicked as follows:
Private Sub dgvNormalReports_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvNormalReports.CellClick
If mblnSuppressUI Then Exit Sub
mblnSuppressUI = True
If e.ColumnIndex >= 0 And e.ColumnIndex <= dgvNormalReports.ColumnCount - 1 And e.RowIndex >= 0 And e.RowIndex <= dgvNormalReports.Rows.Count - 1 Then
Select Case dgvNormalReports.Columns(e.ColumnIndex).Name
Case "dclLeaveOnThisList", "dclPrintLetter", "dclNoLetterNeeded" 'mimic radiobutton - turn off other checkboxes
dgvNormalReports.Rows(e.RowIndex).Cells("dclLeaveOnThisList").Value = False
dgvNormalReports.Rows(e.RowIndex).Cells("dclPrintLetter").Value = False
dgvNormalReports.Rows(e.RowIndex).Cells("dclNoLetterNeeded").Value = False
'N.B. current cell's checked status is changed AFTER this event
Case Else
'ignore
End Select
End If
mblnSuppressUI = False
End Sub
The problem I am having is that if the user clicks on a checkbox that is already checked, it becomes unchecked, and then none of the three checkboxes are checked. I always want one (and only one) checkbox ticked at all times.
Use CurrentCellDirtyStateChanged event handler.
Private Sub dgvNormalReports_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles dgvNormalReports.CurrentCellDirtyStateChanged
If Me.dgvNormalReports.IsCurrentCellDirty = True Then
If Me.dgvNormalReports.CurrentCell.OwningColumn.GetType() = GetType(DataGridViewCheckBoxColumn) Then
If Me.dgvNormalReports.CurrentCell.Value = False Then
'Update only if changed from false to true
If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclLeaveOnThisList") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclLeaveOnThisList").Value = False
If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclPrintLetter") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclPrintLetter").Value = False
If Me.dgvNormalReports.CurrentCell.OwningColumn.Name.Equals("dclNoLetterNeeded") = false Then Me.dgvNormalReports.CurrentRow.Cells("dclNoLetterNeeded").Value = False
Me.dgvNormalReports.CommitEdit(DataGridViewDataErrorContexts.Commit)
Else
'Prevent changes
Me.dgvNormalReports.CancelEdit()
End If
End If
End If
End Sub
If you have predefined columns in datagridview, then may be better will be used a generated by VisualStudio column objects:
Me.dclLeaveOnThisList.Name
Me.dclPrintLetter.Name
Me.dclNoLetterNeeded.Name
First step, edit your three DataGridView columns and set each columns property ReadOnly to true (this will prevent user from changing the values)
dclLeaveOnThisList
dclPrintLetter
dclNoLetterNeeded
and second, use the following code below
Private Sub dgvNormalReports_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvNormalReports.CellClick
If mblnSuppressUI Then Exit Sub
mblnSuppressUI = True
If e.ColumnIndex >= 0 And e.ColumnIndex <= dgvNormalReports.ColumnCount - 1 And e.RowIndex >= 0 And e.RowIndex <= dgvNormalReports.Rows.Count - 1 Then
Dim tmpColName As String = dgvNormalReports.Columns(e.ColumnIndex).Name
With dgvNormalReports.Rows(e.RowIndex)
Select Case tmpColName
Case "dclLeaveOnThisList", "dclPrintLetter", "dclNoLetterNeeded" 'mimic radiobutton - turn off other checkboxes
'Unchecked all checkboxes besides the selected one
If tmpColName <> "dclLeaveOnThisList" Then .Cells("dclLeaveOnThisList").Value = False
If tmpColName <> "dclPrintLetter" Then .Cells("dclPrintLetter").Value = False
If tmpColName <> "dclNoLetterNeeded" Then .Cells("dclNoLetterNeeded").Value = False
'Ensures that the selected cell is checked
.Cells(e.ColumnIndex).Value = True
End Select
End With
End If
mblnSuppressUI = False
End Sub
You can use a combination of these DataGridView events:
CellValueChanged
CurrentCellDirtyStateChanged
CellBeginEdit
You can use CellValueChanged instead of CellClick because CellClick event occurs when any part of a cell is clicked, including borders and padding (MSDN).
CurrentCellDirtyStateChanged event commit the change when the CheckBox is clicked.
The code in CellBeginEdit prevents user from modify a checked CheckBox.
This is an example:
Private Sub DataGridView1_CellValueChanged(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
With Me.DataGridView1
.CurrentCell.Value = True
If .Columns(e.ColumnIndex).Name = "dgvchkOptionA" Then
.Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
.Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionB" Then
.Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
.Rows(e.RowIndex).Cells("dgvchkOptionC").Value = False
ElseIf .Columns(e.ColumnIndex).Name = "dgvchkOptionC" Then
.Rows(e.RowIndex).Cells("dgvchkOptionA").Value = False
.Rows(e.RowIndex).Cells("dgvchkOptionB").Value = False
End If
End With
End Sub
Private Sub DataGridView1_CurrentCellDirtyStateChanged(sender As Object, e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
If Me.DataGridView1.IsCurrentCellDirty Then
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
Private Sub DataGridView1_CellBeginEdit(sender As Object, e As System.Windows.Forms.DataGridViewCellCancelEventArgs) Handles DataGridView1.CellBeginEdit
With Me.DataGridView1
If .CurrentCell Is .Rows(e.RowIndex).Cells(e.ColumnIndex) And _
.CurrentCell.Value Then e.Cancel = True
End With
End Sub