Visual Basic random number for multiple variables - vb.net

Goal: To make a game were a user will select from 16 different options and receive 16 unique responses. These responses are simple security tips for user training.
They must be in random order so nobody can screen look and predict which button yields which result and they cannot be reused/duplicate responses during a single game.
I have been going back and forth on either to use an array or the select case. The select case is looking more promising, however I am not sure how to assign, randomly, 16 different buttons to provide the correct not repeating responses.
Poor code as requested,
'Create Select Case random value and assign to buttons
Do
btn2 = CInt(Int((3 * Rnd()) + 1))
'lblDescript so I can see what btn2 is outputting
lblDescript.Text = btn2.ToString
Loop While btn2 <> btn1 Or btn3
'***************************************************************************************
'Game Buttons 2 - 16 ************************************************************
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Button Style
Button2.ForeColor = Color.Transparent
Button2.BackColor = Color.Transparent
Button2.FlatStyle = FlatStyle.Flat
Button2.Text = ""
Button2.UseVisualStyleBackColor = False
'Button2.Enabled = False
'Select Case
Select Case btn2
Case Is = 1
PictureBox1.Image = My.Resources.Login
Button2.BackgroundImage = My.Resources.Login
lblPicName.Text = "Two - Factor Authentication"
lblDescript.Text = "Two - Factor Authentication, or 2FA adds an extra step to a basic log-in procedure."
Case Is = 2
'Content PaceHolder*****
PictureBox1.Image = My.Resources.Cloud
Button2.BackgroundImage = My.Resources.Cloud
lblPicName.Text = "Two - Factor Authentication"
lblDescript.Text = "Two - Factor Authentication, or 2FA adds an extra step to a basic log-in procedure."
Case Is = 3
'Content PaceHolder*****
PictureBox1.Image = My.Resources.Pwmanager
Button2.BackgroundImage = My.Resources.Pwmanager
lblPicName.Text = "Two - Factor Authentication"
lblDescript.Text = "Two - Factor Authentication, or 2FA adds an extra step to a basic log-in procedure."
Case Is = 4
End Select
The picture I have provided shows what I need to happen when I select the first button in the application.
Image to illustrate:
Once the user selects the button the photo will be displayed as the button as well as off to the right with the name and description.

I think you should pursue a solution that is more based on data instead of code. Your code seems to be hard-wiring a good deal of similar or duplicate logic whereas you could just store all the possibilities in a data structure and shuffle it around. Then you would only use the code to present the shuffled results.
Public Class Form1
Class SecurityTip
Public PicName As String
Public Description As String
Public Image As Image
End Class
Private TipList As SecurityTip()
Private ButtonArray As Button()
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
ButtonArray = New Button() {
Button1, Button2, Button3, Button4, Button5, Button6, Button7, Button8,
Button9, Button10, Button11, Button12, Button13, Button14, Button15, Button16}
For I As Integer = 0 To ButtonArray.Length - 1
AddHandler ButtonArray(I).Click, AddressOf Button_Click
Next
InitializeTips()
ShuffleTips()
End Sub
Public Sub InitializeTips()
TipList = New SecurityTip() {
New SecurityTip() With {
.Image = My.Resources.Login,
.PicName = "Two - Factor Authentication",
.Description = "Two - Factor Authentication, or 2FA adds an extra step to a basic log-in procedure."},
New SecurityTip() With {
.Image = My.Resources.Cloud,
.PicName = "Cloud Authentication",
.Description = "Cloud authentication might also be referred to as federated identity or something."},
New SecurityTip() With {
.Image = My.Resources.Pwmanager,
.PicName = "Password Manager",
.Description = "Password managers help users maintain separate passwords for different sites."}
}
End Sub
Public Sub ShuffleTips()
Dim R As New Random()
For i As Integer = 0 To TipList.Length - 1
Dim SwapIndex = R.Next(TipList.Length)
Dim Temp = TipList(SwapIndex)
TipList(SwapIndex) = TipList(i)
TipList(i) = Temp
Next
End Sub
Public Sub PresentTip(Index As Integer)
With TipList(Index)
PictureBox1.Image = .Image
lblPicName.Text = .PicName
lblDescript.Text = .Description
ButtonArray(Index).BackgroundImage = TipList(Index).Image
End With
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs)
For I As Integer = 0 To ButtonArray.Length - 1
If ButtonArray(I) Is sender Then
PresentTip(I)
Exit Sub
End If
Next
End Sub
End Class

In your code, below
'Button2.Enabled = False
Add
Dim rndNum As Random
Dim randomChoice As Integer = rndNum.Next(1, 4)
and your select case statement to
Select Case randomChoice
Case 1
Case 2
Case 3
Case 4
including the code for each of course.

Related

Trouble with variables, I am making Yahtzee for a school project and can't get some code to work and am still learning how to code

This is my first question in this community and I'd like some help with a school project I am doing.
I am implementing a turn system where every time you select a method to score a variable called turn increases by one so that the appropriate label is changed to the points you got that turn.
This is an example of the Ones option to score which checks all the dice and adds up all the dice which have the value one, when the Ones button is pressed it should update the current turn with the points gained. At the moment it only updates the first turns score. The second and third images are of the changes I tried making which don't work.
[Ones][1]
[Ones changed][2]
[Ones error][3]
```
Private Sub btnOnes_Click(sender As Object, e As EventArgs) Handles btnOnes.Click
Dim Nums(4) As Integer
Nums(0) = RandomNum1
Nums(1) = RandomNum2
Nums(2) = RandomNum3
Nums(3) = RandomNum4
Nums(4) = RandomNum5
For i = 0 To 4
If Nums(i) = 1 Then
OnesScore += 1
End If
Next
lblTurnValue1.Text = OnesScore
Turn += 1
btnOnes.Enabled = False
End Sub
Private Sub btnOnes_Click(sender As Object, e As EventArgs) Handles btnOnes.Click
Dim Nums(4) As Integer
Nums(0) = RandomNum1
Nums(1) = RandomNum2
Nums(2) = RandomNum3
Nums(3) = RandomNum4
Nums(4) = RandomNum5
For i = 0 To 4
If Nums(i) = 1 Then
OnesScore += 1
End If
Next
lblTurnValue1(Turn).Text = OnesScore
Turn += 1
btnOnes.Enabled = False
End Sub
Another problem I have been having is automatically updating labels as I want to make a Newbie mode for my Yahtzee game which displays the numbers beside each option to score so you know what score you are going to get before you choose.
I can't use the Ones button for clicking to represent the score because it's used for scoring the points and whenever I try double click on the label to show its code in Visual Studio it only updates in game when the person clicks the number to show their score which is not what I desire.
[Ones label][4]
Private Sub lblOnes_Click(sender As Object, e As EventArgs) Handles lblOnes.Click
lblOnes.Text = OnesScore
End Sub
In short I want to learn how to use variables within names of objects to allow for the right one to be chosen and how to update labels automatically instead of having to click them. Any resources you can provide to further my understanding of VB.NET is really helpful.
Thanks.
[1]: https://i.stack.imgur.com/zUQM6.png
[2]: https://i.stack.imgur.com/c5nJe.png
[3]: https://i.stack.imgur.com/Y3gUE.png
[4]: https://i.stack.imgur.com/BnwZ8.png

How to customize a "MsgBox" control in Visual Basic

Is there a way to customize the MsgBox control in Visual Basic?
I use it quite often to alert users. However it never pops up on the screen; it just appears along the bottom task bar. It also always has a heading similar to "App_data_xxx". Can I improve this in any way?
My searches aren't throwing up much help.
For example:
' Queries user number and password against the database and returns user
Dim matchingusers = From u In db.Users
Where username = u.Email And password = u.Password
Select u
' Checks if a valid user was returned
If matchingusers.Count = 0 Then
MsgBox("Invalid user entered, try again")
Else
SelectedDeveloper = 0
' Set the logged in user for use in the project
GlobalVariables.LoggedInUser = matchingusers.First
You can use the MessageBox function and its many variables. Here's an example of what it can do:
MessageBox.Show("The Displayed text in the messagebox", _
"the text displayed in the title bar", MessageBoxButtons.YesNoCancel, _
MessageBoxIcon.Error, MessageBoxDefaultButton.Button2)
Or you can still use MsgBox and use its variables, though it gives you fewer options. Here's an example:
MsgBox("message text", MsgBoxStyle.Information, "title bar text")
You are using a reference to the MessageBox class without specifying the Method you want to call. You cannot create an instance of MessageBox and therefore cannot pass a string as parameter to try and create one.
Use MessageBox.Show(string messageText) to display the MessageBox with the desired message.
As for your question, you should create your own MessageBox class. With this solution, you get all the options you want and can customize it completely. The call will be a little different :
//C#
var myCustomMessageBox = new CustomMessageBox();
myCustomMessageBox.ShowDialog();
//Vb
Dim myCustomMessageBox As New CustomMessageBox()
myCustomMessageBox.ShowDialog()
The ShowDialog() will be used to create the effect of a messagebox.
In Visual Basic 2008 I had a requirement for a message box that would only stay on for short times and that the time it was on to be variable. I also had the problem that when using extended screen that the msgbox showed up on the extended screen (which was a different form) instead of on the main computer screen. To overcome these problems I created a custom Message Box using a panel on the form I had on the main screen.
To call the message panel DoMessage("The message", Seconds, Buttons to show 1 = Ok only 2 = Yes(ok) and No, 3 = Yes, No and Cancel. If seconds is 0 or not specified then the time to show the panel is set to a long time (10000 seconds) If Buttons to show is not specified it is set to Ok button only. If seconds and buttons are both specified, If no button is clicked the panel will just hide after the timeout.
The responses are 1 if Ok or Yes is clicked, 2 if No is clicked, 3 if Cancel is clicked
It is put into DoMsgResp so you see what is in it to handle the response.
Create the message panel when opening the form by calling MakeMsgPanel()
Dim MessagePanel As New Panel 'The panel
Dim MessageLabel As New Label 'The message
Dim MsgYes As New Button 'Yes or OK button
Dim MsgNo As New Button 'no button
Dim MsgCcl As New Button 'Cancel button
Dim Sleepsecs As Integer 'How long panel shows for
Dim DoMsgResp As Integer 'response 1, 2 or 3 depending which button clicked
Private Sub MakeMsgPanel()
Me.Controls.Add(MessagePanel)
Me.MessagePanel.Controls.Add(MessageLabel)
Me.MessagePanel.Controls.Add(MsgYes)
Me.MessagePanel.Controls.Add(MsgNo)
Me.MessagePanel.Controls.Add(MsgCcl)
MessagePanel.Location = New System.Drawing.Point(Me.Width / 2 - 200, Me.Height / 2 - 100)
MessagePanel.BackColor = Color.PaleGreen
MessageLabel.BackColor = Color.PeachPuff
MessagePanel.BorderStyle = BorderStyle.FixedSingle
MessageLabel.Font = New Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Point)
MessageLabel.AutoSize = True
MessagePanel.AutoSize = True
MessagePanel.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowOnly
MessagePanel.Hide()
MsgYes.Location = New System.Drawing.Point(205, 5)
MsgNo.Location = New System.Drawing.Point(115, 5)
MsgCcl.Location = New System.Drawing.Point(25, 5)
MsgYes.Text = "Yes"
MsgNo.Text = "No"
MsgCcl.Text = "Cancel"
AddHandler MsgYes.Click, AddressOf MsgYes_Click
AddHandler MsgNo.Click, AddressOf MsgNo_Click
AddHandler MsgCcl.Click, AddressOf MsgCcl_Click
End Sub
Private Sub MsgYes_Click()
DoMsgResp = 1
Sleepsecs = 0
End Sub
Private Sub MsgNo_Click()
DoMsgResp = 2
Sleepsecs = 0
End Sub
Private Sub MsgCcl_Click()
DoMsgResp = 3
Sleepsecs = 0
End Sub
Private Sub DoMessage(ByVal Msg As String, Optional ByVal Secs As Integer = 0, _
Optional ByVal Btns As Integer = 0)
'Information messages that can be timed
Dim TheHeight As Integer
Dim TheWidth As Integer
Dim Labelx As Integer
Dim Labely As Integer
DoMsgResp = 0
MessageLabel.Text = Msg
If MessageLabel.Height < 90 Then
TheHeight = 100
Labely = (100 - MessageLabel.Height) / 2
Else
TheHeight = MessageLabel.Height + 10
Labely = 5
End If
If MessageLabel.Width < 140 Then
TheWidth = 150
Labelx = (150 - MessageLabel.Width) / 2
Else
TheWidth = MessageLabel.Width + 10
Labelx = 5
End If
MessagePanel.Size = New System.Drawing.Size(TheWidth, TheHeight)
MessageLabel.Location = New System.Drawing.Point(Labelx, Labely)
MessageLabel.Show()
MessagePanel.Show()
MessagePanel.BringToFront()
MsgYes.BringToFront()
MsgNo.BringToFront()
MsgCcl.BringToFront()
MessagePanel.Focus()
If Btns = 0 Or Btns > 3 Then Btns = 1 'Make ok button if none specified or number too high
If Btns = 1 Then
MsgYes.Text = "Ok"
MsgNo.Hide()
MsgCcl.Hide()
Else 'is 2 or 3
MsgYes.Text = "Yes"
MsgNo.Show()
If Btns = 2 Then MsgCcl.Hide() Else MsgCcl.Show()
End If
If Secs = 0 Then Secs = 10000 'make a long time
If Secs > 0 Then
Sleepsecs = Secs * 2
Do Until Sleepsecs < 1
Threading.Thread.Sleep(500)
Application.DoEvents()
Application.RaiseIdle(New System.EventArgs)
Sleepsecs = Sleepsecs - 1
Loop
End If
MessagePanel.Hide()
End Sub
Private Sub ButtonTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonTest.Click
DoMessage("This is To see what happens with my message" & vbCrLf & _
"see if it works good", 0, 3)
If DoMsgResp = 1 Then
MsgBox("Ok was hit")
End If
If DoMsgResp = 2 Then
MsgBox("No was hit")
End If
If DoMsgResp = 3 Then
MsgBox("Cancel was hit")
End If
End Sub

Trouble with Timer_tick not stopping

I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer

DataGridView not Refreshing/Updating/Reloading Data. After Child form closes

This is a VB.NET, Winforms App. I have a datagridview on "Form1" that uses a databinding.datasource which is an Entity Framework table. I fill the datagridview with the below function on Form1:
Sub PM_UnitViewGrid()
Try
_form1.UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = _form1.CurrentPropertyId).OrderBy(Function(F) F.unitNumber)
_form1.UnitDataGridView.DataSource = _form1.UnitsBindingSource.DataSource
Dim iCount As Integer = _form1.UnitDataGridView.RowCount
For x As Integer = 0 To iCount - 1
If Not IsNothing(_form1.UnitDataGridView.Rows(x).Cells(4).Value) Then
Dim tid As Integer = _form1.UnitDataGridView.Rows(x).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = tid)
_form1.UnitDataGridView.Rows(x).Cells(1).Value = _ten.first_name + ", " + _ten.last_name
Else
Dim btnColumn As DataGridViewButtonCell = CType(_form1.UnitDataGridView.Rows(x).Cells(1), DataGridViewButtonCell)
btnColumn.Style.BackColor = Color.Green
_form1.UnitDataGridView.Rows(x).Cells(1).Value = "VACANT"
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Return
End Sub
This works great and also assigns the needed values to an unbound column. The problem is that the cells(1) is a button. Which when clicked takes the user to another form as a new dialog window. The function for which is below. However, once the changes are made in that form I need for the datagridview to refresh the data that its using from the database and show the correct data. As it stands right now the values are not updating on the datagridview unless the app is completely exited and restarted. Nothing I have found seems to work and Refresh and Update only redraw the control. I need the underlying datasource to refresh and then the datagridview once the child form is exited.. This has had me stumped for a good 36 hours now and I am lost as to why nothing I am trying is working. ANY and all help would be greatly appreciated.
The sub that loads the child form based on the cells(1) button clicked is as follows:
Private Sub UnitDataGridView_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles UnitDataGridView.CellContentClick
UnitDataGridView.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)
Dim y As DataGridViewCellEventArgs = e
Dim Tid As Integer = Nothing
If e.ColumnIndex = 1 Then
If Not e.RowIndex = -1 Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
currentTenent = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
TenentIdentification = currentTenent
If Not IsNothing(e) Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
Tid = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = Tid) 'tenant is a table entity
TenantViewSubs.tenId = _ten.Occupantid
Dim t As New TenantView
t.tenId = tid
t.ShowDialog()
End If
End If
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
Else
Dim uTview As New UnassignedTenants
uTview.selectedProperty = selectedProperty 'selectedProperty is Integer
uTview.ShowDialog()
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
End If
End If
End If
End Sub
I tried each of the following code blocks after the t.ShowDialog() line with no change at all.
UnitDataGridView.Refresh()
.
UnitsBindingSource.Dispose()
UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
.
UnitsBindingSource.DataSource = nothing
unitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
I finally fixed this on my own.. It was in the way I passed my db context to the databinding..
I simply wrote the below sub:
Private Sub UpdateValues()
Dim context As New storageEntities 'storageEntities is an Entity
Dim query = context.units.Where(Function(F) F.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = query
End Sub
Then anytime a child form updated data I simply call
UpdateValues()
After the dialog box closes.
This may help someone else with the same problems so that is why I am posting it.

Public subs don't work in this scenario

I have a form named FrmDrvouchers. It contains some public subprocedures.
I call these subs from another form which opens from a form which is opened from FrmDrVouchers as a dialog.
When I open FrmDrvouchers directly, everything works. But when I call FrmDrvouchers from another project which is also part of this solution, its public subs don't work when I call them from another (dialog) form.
Here is the code of the Button Click from which I open FrmDrvouchers:
Dim FrmDrv As FrmDrVouchers = New FrmDrVouchers()
FrmDrv.Show()
This works, but those public subs don't. Why?
Thanks For ur response,
It just skip what i want to do, but not throws any Exceptions,
Now I m posting my Code,,, plz have a look on that,,
Here is my Main form's MenuStrip Button Click code :
Private Sub CashPaymentToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CashPaymentToolStripMenuItem.Click
Dim DrVouchers As Transactions.FrmDebitVouchers = Transactions.New FrmDebitVouchers()
DrVouchers.Show()
End Sub
Here is the FrmDebitVouchers's Public Subs which are not working,,, in the sense that they skip the function which i have written but not throwing any Exception,,
Public Sub DrVoucherOPen(ByVal VoucherNo As Integer)
'Filling the Dataset with selected Voucher No to OPen the record
DebitVouchersTableAdapter.FillByVoucher(Flr12131DataSet.DebitVouchers, VoucherNo)
VoucherDateDateTimePicker.Enabled = False
End Sub
Public Sub DrVoucherBodyOPen(ByVal VoucherNo As Integer)
'---------Procedure to Open DrVouchersBody And to OPen it in Datagridview-------------'
'Getting the User No, and if it is admin then load fill dataset and allow user to edit the record
If GetUserNumber() = 1 Then
'Filling the dataset
DebitVouchersBodyTableAdapter.FillByVoucher(Flr12131DataSet.DebitVouchersBody, VoucherNo)
DrBodyDGV.DataSource = Nothing
Dim Sum As New Decimal
'Initializing the SerialNumbers variable
SerialNumbers = New List(Of Integer)
'Setting datagridview to opend record
For i = 0 To Flr12131DataSet.DebitVouchersBody.Rows.Count - 1
DrBodyDGV.Rows.Add()
DrBodyDGV.Rows(i).Cells(0).Value = Flr12131DataSet.DebitVouchersBody.Rows(i).Item("SerialNo")
DrBodyDGV.Rows(i).Cells(3).Value = Flr12131DataSet.DebitVouchersBody.Rows(i).Item("AccountNo")
DrBodyDGV.Rows(i).Cells(6).Value = Flr12131DataSet.DebitVouchersBody.Rows(i).Item("Debit")
DrBodyDGV.Rows(i).Cells(7).Value = Flr12131DataSet.DebitVouchersBody.Rows(i).Item("Narration")
'Getting serial No into List
SerialNumbers.Add(Flr12131DataSet.DebitVouchersBody.Rows(i).Item("SerialNo"))
'Getting Account Name into Datagridview
If Not Not IsNumeric(DrBodyDGV.Rows(i).Cells(3).Value) Then
Dim Qa As New Flr12131DataSetTableAdapters.QueriesTableAdapter
Dim StrAccountName = Qa.GetAccountName(DrBodyDGV.Rows(i).Cells(3).Value)
DrBodyDGV.Rows(i).Cells(5).Value = StrAccountName
Else
End If
Sum += DrBodyDGV.Rows(i).Cells(6).Value
Next
TxtTotal.Text = Sum
'Setting the controls properties for admin
DrBodyDGV.AllowUserToAddRows = True
DrBodyDGV.AllowUserToDeleteRows = True
DrBodyDGV.ReadOnly = False
BtnSave.Enabled = True
BtnDelete.Enabled = True
BtnPrint.Enabled = True
ToUpdate = True
Else
'If user is not admin then load all record and not allow user to modify it or delete
' Bounding the datagridview
Dim Sum As Decimal = 0
BtnSave.Enabled = False
DebitVouchersBodyTableAdapter.FillByVoucher(Flr12131DataSet.DebitVouchersBody, VoucherNo)
DrBodyDGV.DataSource = Flr12131DataSet.DebitVouchersBody
For i = 0 To DrBodyDGV.Rows.Count - 1
If Not Not IsNumeric(DrBodyDGV.Rows(i).Cells(3).Value) Then
Dim Qa As New Flr12131DataSetTableAdapters.QueriesTableAdapter
Dim StrAccountName = Qa.GetAccountName(DrBodyDGV.Rows(i).Cells(3).Value)
DrBodyDGV.Rows(i).Cells(5).Value = StrAccountName
Else
End If
Sum += DrBodyDGV.Rows(i).Cells(6).Value
Next
TxtTotal.Text = Sum
DrBodyDGV.AllowUserToAddRows = False
DrBodyDGV.AllowUserToDeleteRows = False
' DrBodyDGV.edit()
DrBodyDGV.ReadOnly = True
BtnSave.Enabled = False
BtnDelete.Enabled = False
BtnPrint.Enabled = True
End If
End Sub
Here is another the DrVouchersRecord form from which I call Public Subs:
Private Sub DrVouchersRecordDataGridView_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DrVouchersRecordDataGridView.CellDoubleClick
Dim FrmDrVouchers As FrmDebitVouchers = New FrmDebitVouchers()
If FrmDrVouchers.DrBodyDGV.Rows.Count > 1 Then
Dim Ans As Integer
Ans = MsgBox("Unsaved changes will be lost, want to proceed", vbYesNo + vbInformation, "Alert")
If Ans = vbYes Then
Dim VoucherNo As New Integer
VoucherNo = DrVouchersRecordDataGridView.CurrentRow.Cells(0).Value
FrmDrVouchers.DrVoucherOPen(VoucherNo)
FrmDrVouchers.DrVoucherBodyOPen(VoucherNo)
Me.Close()
End If
Else
Dim VoucherNo As New Integer
VoucherNo = DrVouchersRecordDataGridView.CurrentRow.Cells(0).Value
FrmDrVouchers.DrVoucherOPen(VoucherNo)
FrmDrVouchers.DrVoucherBodyOPen(VoucherNo)
Me.Close()
End If
End Sub
My forms sequence is:
FrmMain is my main startUp form
After that FrmDebitVouchers Open on menustripButtonclick
After that DebitVouchersRecord is Open as Dialog from DrmDebitVouchers,,, and from these Public Subs are called
I Have added Refrence also
Waiting for ur answers,
This problem has hit many programmers coming from VB6 to VB.NET.
In your DataGridView_DoubleCellClick event you create a NEW instance of FrmDebitVouchers.
Then your code refers to property/methods/objects of this new INSTANCE, not of the original one created via CashPaymentToolStripMenuItem_Click. (Also note that this new instance is never showed on the screen, so you are sending/requesting changes to an hidden form instance)
Of course, the DrBodyDGV.Rows.Count is zero on this INSTANCE (referenced as FrmDrVouchers) because probably this INSTANCE has never been intialized like the first one.
Try to add a FrmDrVouchers.Show() after the creation and you will see the hidden SECOND INSTANCE of the form class FrmDebitVouchers.
To solve your problem, you need to pass the reference of the first FrmDebitVouchers instance to the DrVouchersRecord form (for example in the constructor or via a public property) and then use that reference instead of creating FrmDrVouchers