Trouble with Timer_tick not stopping - vb.net

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

Related

What has to be done to show a marquee output with a scroll menu?

Today i continue my work, Building a menu with a vb.net console application. I found more samples to build with Windows forms. Still i try to get Basic Knowledge with the console surface.I was not able to put the following marquee text in a scroll menu, the second Code past the marquee text.
Module Module1
Dim aTimer As New System.Timers.Timer
Const marqueeText As String = "The quick brown fox... "
Dim sb As New System.Text.StringBuilder
Dim direction As Boolean = False
Sub Main()
aTimer.AutoReset = True
aTimer.Interval = 100 '1/10 second
AddHandler aTimer.Elapsed, AddressOf tick
aTimer.Start()
Console.ReadKey()
End Sub
Private Sub tick(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
Console.Clear()
If sb.Length = 0 Then sb.Append(marqueeText)
If direction Then
sb.Insert(0, sb(sb.Length - 1))
sb.Remove(sb.Length - 1, 1)
Else
sb.Append(sb(0))
sb.Remove(0, 1)
End If
Console.CursorLeft = 10 'no visible change
Console.CursorTop = 10 'visible change
Console.Write("{0}{1}", vbCr, sb.ToString)
End Sub
End Module
The marquee text Output from above is not easy to manage with the console.cursorleft command. I have no clue how to move it to the right or to put the marquee Output in the following Code, a scroll menu, on the third line.
Module Module1
Dim MenuList As New List(Of String)
Sub PrintMenu(highlight As Integer, left As Integer, top As Integer)
Dim Nickvektor() As Integer = {1, 2, 3, 4, 5}
For I = 0 To MenuList.Count - 1
Console.CursorLeft = left
Console.CursorTop = top + I
If I = highlight Then
Console.Write("{0}", "[" & Nickvektor(I) & "]")
Else
Console.Write(MenuList(I))
End If
Next
End Sub
Sub Main()
Console.CursorVisible = False
Dim x As Integer = 0
Dim Nickvektor() As String = {" "}
For counter As Integer = 0 To 0
Do
For Each s In Nickvektor
MenuList.Add(s)
Next
x += 1
Loop Until x = 5
Next
Console.SetCursorPosition(10, 16)
Console.Write("[ ]")
Dim CurrentItem As Integer = 0
Dim CurrentKey As ConsoleKey
While CurrentKey <> ConsoleKey.Enter
PrintMenu(CurrentItem, 10, 10)
CurrentKey = Console.ReadKey(True).Key
Select Case CurrentKey
Case ConsoleKey.DownArrow
CurrentItem += 1
Case ConsoleKey.UpArrow
CurrentItem -= 1
End Select
CurrentItem = (CurrentItem + MenuList.Count) Mod MenuList.Count
End While
End Sub
End Module
The menu Frame for the above Code can be used with the up and down arrows on the Keyboard.
Maybe it is to much work but i have no clue how to continue.
The first Solution for the marquee Output is an easy change of the original code. The wrap, vbCr, was the main Problem to move the text output toward the right edge oft he screen. The following code can be used to change the cursorTop Positon and also the cursorLeft Position of the Text.
Console.CursorVisible = False
Console.CursorLeft = 30
Console.CursorTop = 10
Console.Write("{0}", sb.ToString)
The heavy part are the Menu code Lines. To answer my own question some additional help was necessary.
I posted my question on the MS developer Network written in german language. With the following link it can be viewed.
For the case the link should be broken or other cases i post the code on this site.
Module Module1
Dim MenuList As New List(Of String)
Dim aTimer As New System.Timers.Timer
Const marqueeText As String = "The quick brown fox... "
Dim sb As New System.Text.StringBuilder
Dim direction As Boolean = False
Sub PrintMenu(highlight As Integer, left As Integer, top As Integer)
Dim Nickvektor() As Integer = {1, 2, 3, 4, 5}
For I = 0 To MenuList.Count - 1
Console.CursorLeft = left
Console.CursorTop = top + I
If I = highlight Then
Console.Write("{0}", "[" & Nickvektor(I) & "]")
Else
Console.Write(MenuList(I))
End If
Next
End Sub
Sub Main()
Console.CursorVisible = False
aTimer.AutoReset = True
aTimer.Interval = 100 '1/10 second
AddHandler aTimer.Elapsed, AddressOf tick
Dim x As Integer = 0
Dim Nickvektor() As String = {" "}
For counter As Integer = 0 To 0
Do
For Each s In Nickvektor
MenuList.Add(s)
Next
x += 1
Loop Until x = 5
Next
Console.SetCursorPosition(10, 16)
Console.Write("[ ]")
Dim CurrentItem As Integer = 0
Dim CurrentKey As ConsoleKey
While CurrentKey <> ConsoleKey.Enter
If CurrentItem = 2 Then ' Zero can be used to show the marquee output prompt
aTimer.Start() ' With a change to two or four the timer can be stoped:
'Else
'If aTimer.Enabled Then
' aTimer.Stop()
'End If
End If
PrintMenu(CurrentItem, 10, 10)
CurrentKey = Console.ReadKey(True).Key
Select Case CurrentKey
Case ConsoleKey.DownArrow
CurrentItem += 1
Case ConsoleKey.UpArrow
CurrentItem -= 1
End Select
CurrentItem = (CurrentItem + MenuList.Count) Mod MenuList.Count
End While
End Sub
Private Sub tick(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
If sb.Length = 0 Then sb.Append(marqueeText)
If direction Then
sb.Insert(0, sb(sb.Length - 1))
sb.Remove(sb.Length - 1, 1)
Else
sb.Append(sb(0))
sb.Remove(0, 1)
End If
Console.CursorVisible = False
Console.CursorLeft = 20
Console.CursorTop = 12 ' For the first Element CursorTop=10, fort he third 12
Console.Write("{0}", sb.ToString)
End Sub
End Module
To learn an other language like English i have to search a lot. Visual Basic Code is mostly written with English key words for the commands. I think it is easier to look up the maintainable changes for your self. To search is not every day funny.

ArgumentOutOfRangeException when trying to clear combobox

I'm having the following error message appear when trying to run .Clear() on my combobox:
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in System.Windows.Forms.dll
{"InvalidArgument=Value of '-1' is not valid for 'index'.
Parameter name: index"}
The strange part is, it does the .Clear() before going to the new 'page' in the application, and it works without a problem. Once I'm on the 'page', draw the items in the combobox and try to go to the next 'page' of the application, it calls the function with the clear once again and blows up when it gets to the .Clear(). If I comment out the cbo.DrawMode = DrawMode.OwnerDrawFixed in the code below it also runs as normal, so the problem is definitely with drawing the strings in the combobox (I'm drawing the strings to change the colour of them). Anyways, completely stumped as to how to fix this, any help would be appreciated.
Code is below:
-My clear method
Public Sub ClearCombos()
'Clear Applicant Combos
cboPrimary.Items.Clear() 'crashes when it hits this line
cboJoin1.Items.Clear()
cboJoin2.Items.Clear()
cboJoin3.Items.Clear()
cboJoin4.Items.Clear()
End Sub
Drawing the strings in the comboboxes
Sub CheckForAgeOverage()
c_applicants = {cboPrimary, cboJoin1, cboJoin2, cboJoin3, cboJoin4}
Dim curdate As Date = Date.Now
Dim age As Integer
counter = 0
'Check age of applicants
For Each cbo As ComboBox In c_applicants
If CKeyValuePair.GetComboBoxSelectedKey(c_applicants(counter), True) = instApplicant.applicantId Then
age = Math.Floor(DateDiff(DateInterval.Month, DateValue(instApplicant.BirthDate), curdate) / 12)
If age >= 70 Then
overArray.Add(CKeyValuePair.GetComboBoxSelectedValue(c_applicants(counter)))
End If
cbo.DrawMode = DrawMode.OwnerDrawFixed
Else
For Each j As JoinsBU In instJoins
If CKeyValuePair.GetComboBoxSelectedKey(c_applicants(counter), True) = j.Applicant.applicantId Then
age = Math.Floor(DateDiff(DateInterval.Month, DateValue(j.Applicant.BirthDate), curdate) / 12)
If age >= 70 Then
overArray.Add(CKeyValuePair.GetComboBoxSelectedValue(c_applicants(counter)))
End If
cbo.DrawMode = DrawMode.OwnerDrawFixed
End If
Next
End If
counter += 1
Next
End Sub
The Comboboxes DrawItem event:
Private Sub cbo_DrawItem(sender As System.Object, e As System.Windows.Forms.DrawItemEventArgs) Handles cboPrimary.DrawItem, cboJoin1.DrawItem, cboJoin2.DrawItem, cboJoin3.DrawItem, cboJoin4.DrawItem
Dim brush As Brush = Brushes.Black
Dim text As String = (CType(sender, ComboBox)).Items(e.Index).ToString()
counter = 0
For Each s As String In overArray
If text = overArray(counter) Then
brush = Brushes.Red
Else
brush = Brushes.Black
End If
counter += 1
Next
e.Graphics.DrawString(sender.Items(e.Index).ToString(), e.Font, brush, _
e.Bounds, StringFormat.GenericDefault)
counter = 0
End Sub
It looks like this shouldn't happen, but it obviously is. The actual error might be in this line in the DrawItem handler:
Dim text As String = (CType(sender, ComboBox)).Items(e.Index).ToString()
Try separating the assignment out of the Dim statement, and check the value of e.Index to make sure it is non-negative. If that's the problem, you could probably work around it with an if to make sure e.Index is non-negative.

What else can cause an AxWindowsMediaPlayer to play?

I have a button in my program that grabs a bunch of information from a DataGridView object (volume, url, delay, etc) and using that, it plays a file. I'm trying to get the delay to work (wait x number of seconds before playing) and I'm pretty it will work, but whenever I press the button, the play starts immediately. There is no Ctlcontrols.play() anywhere in the program except after the delay, so I have no idea what is causing it to play.
I explained my problem a little bit more in comments. Sorry if I didn't explain my code very well. If you could just tell my what else could be causing my player to start immediately, that would probably be enough.
'snd_btn_go is the button that is supposed to start it.
'This sub doesn't matter as much for the problem, it will just go to SndCueGO() if both numbers are in the valid range.
Private Sub snd_btn_go_Click(sender As Object, e As EventArgs) Handles snd_btn_go.Click
Dim cue1 As Integer
Dim cue2 As Integer
cue1 = If(Integer.TryParse(snd_txt_cue_1.Text, cue1), Int(snd_txt_cue_1.Text), snd_num1)
If snd_txt_cue_2.Text <> "" Then
cue2 = If(Integer.TryParse(snd_txt_cue_2.Text, cue2), Int(snd_txt_cue_2.Text), snd_num2)
Else
cue2 = -1
End If
If (cue1 <= dgSound.Rows.Count - 1 And cue1 > 0) Then
SndCueGO(cue1, cue2)
End If
End Sub
'This sub pulls all the info from the correct row in the DataGrid and assigns it to a list. It'll check if the start volume and end volume are the same and if they're not, it'll fade to the end volume.
Private Sub SndCueGO(cue1, cue2)
Dim cues() = {cue1, cue2}
snd_num1 = cue1
Dim cuedata1 = snd_ds.Tables(0).Rows(cue1 - 1)
Dim cuedata2 = snd_ds.Tables(0).Rows(cue1 - 1)
If cue2 <> -1 Then
snd_num2 = cue2
cuedata2 = snd_ds.Tables(0).Rows(cue2 - 1)
End If
Dim data() = {cuedata1, cuedata2}
For i = 0 To 1
If cues(i) <> -1 Then
snd_delay(i) = data(i).Item("Delay")
snd_startvol(i) = safeNum(data(i).Item("Start_Vol."))
snd_file(i) = data(i).Item("File")
snd_in(i) = data(i).Item("Fade_In")
snd_out(i) = data(i).Item("Fade_Out")
snd_vol(i) = safeNum(data(i).Item("Vol."))
snd_hold(i) = data(i).Item("Hold")
snd_af(i) = If(data(i).Item("AF") = "", False, True)
player_list(i).URL = snd_file(i)
snd_current(i) = snd_startvol(i)
If snd_startvol(i) <> snd_vol(i) Then 'snd_startvol(i) and snd_vol(i) were the same in all my tests, so this should not run.
snd_next(i) = snd_vol(i)
Dim num_steps_up = snd_in(i) * snd_speed
Dim num_steps_down = snd_out(i) * snd_speed
Dim diff = snd_vol(i) - snd_startvol(i)
Dim small_step As Single
If diff > 0 Then
small_step = diff / num_steps_up
ElseIf diff < 0 Then
small_step = diff / num_steps_down
End If
snd_steps(i) = small_step
timer_snd_fade.Tag = 0
timer_snd_fade.Enabled = True
End If
timer_snd_master.Tag = 0 'resets the tag to 0
timer_snd_master.Enabled = True 'Starts timer
End If
Next
End Sub
Private Sub timer_snd_master_Tick(sender As Object, e As EventArgs) Handles timer_snd_master.Tick
If sender.Tag = snd_delay(0) Then
Player1.Ctlcontrols.play() 'This is the only play command in the program
Debug.Print("tag " & sender.Tag) 'These print after the delay
Debug.Print("delay " & snd_delay(0))
End If
sender.Tag += 1
End Sub
Inspect the:
AxWindowsMediaPlayer player1 = ...; // get the player from UI
IWMPSettings sett = player.settings;
sett.autoStart == ??
see the docs.
Probably it is set to true, as it's default value. Simply set it to false it the player will not play until Ctlcontrols.play() is invoked.

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

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.