stuengelman
asked on
Difficulty Getting a .NET PC Application UserControl Button Handler To Work
Hello,
I'm building a PC Application in VS 2008 using VB with .NET Framework 3.5.
I'm having a very strange problem with a button handler in a UserControl.
I use a DialogBox Load handler in three contexts:
(1) Initial load when DialogBox is first popped - load handler works perfectly.
(2) Refreshing DialogBox from DB by pressing a Refresh button (destroying/rebuilding my UserControls, each one populated with data from a DB table row) - code in Refresh button handler performs the UserControl disposals, and then calls the DialogBox Load handler to rebuild the form - this operation works perfectly too.
(3) Pressing an "Add" button on a UserControl - this calls a handler in the UserControl which is coded to load a global string variable with the position to add a blank UserControl, and then invoke the Dialogbox's Refresh button handler to destroy the existing UserControls, and then call the DialogBox load handler to rebuild the form with UserControls containing the blank UserControl in the appropriate position. The purpose of the blank UserControl is to add a new record to the DB on commit (the "Add" button on the blank UserControls says "Enter", and invokes context specific logic to create a new DB record and refresh the form).
I have placed MsgBoxes in multiple places in the Refresh button handler and DialogBox load handler, and it appears that pressing the "Add" button is running through both sets of code, and without abending. But for some reason the form does not repaint; i.e., the expected blank UserControl never materializes.
The DialogBox load handler and Reset button load handler are in the code snippet.
The handler for the UserControl Add button handler is effectively:
glbMiscString = btnMXAdd.Tag
mdgExpListMgr.btnMXReset_C licked()
(I say "effectively" as I am omitting the "Enter" portion of the logic here, as it is not pertinent to this ticket).
Any help would be appreciated.
Thanks, Stu Engelman
I'm building a PC Application in VS 2008 using VB with .NET Framework 3.5.
I'm having a very strange problem with a button handler in a UserControl.
I use a DialogBox Load handler in three contexts:
(1) Initial load when DialogBox is first popped - load handler works perfectly.
(2) Refreshing DialogBox from DB by pressing a Refresh button (destroying/rebuilding my UserControls, each one populated with data from a DB table row) - code in Refresh button handler performs the UserControl disposals, and then calls the DialogBox Load handler to rebuild the form - this operation works perfectly too.
(3) Pressing an "Add" button on a UserControl - this calls a handler in the UserControl which is coded to load a global string variable with the position to add a blank UserControl, and then invoke the Dialogbox's Refresh button handler to destroy the existing UserControls, and then call the DialogBox load handler to rebuild the form with UserControls containing the blank UserControl in the appropriate position. The purpose of the blank UserControl is to add a new record to the DB on commit (the "Add" button on the blank UserControls says "Enter", and invokes context specific logic to create a new DB record and refresh the form).
I have placed MsgBoxes in multiple places in the Refresh button handler and DialogBox load handler, and it appears that pressing the "Add" button is running through both sets of code, and without abending. But for some reason the form does not repaint; i.e., the expected blank UserControl never materializes.
The DialogBox load handler and Reset button load handler are in the code snippet.
The handler for the UserControl Add button handler is effectively:
glbMiscString = btnMXAdd.Tag
mdgExpListMgr.btnMXReset_C
(I say "effectively" as I am omitting the "Enter" portion of the logic here, as it is not pertinent to this ticket).
Any help would be appreciated.
Thanks, Stu Engelman
Private Sub mdgExpListMgr_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
Me.SuspendLayout()
Me.BackgroundImage = Nothing
pbExpListBackground.SendToBack()
Dim myData As DataTable = GetExpenseListData()
Dim ii As Integer = 0
If myData.Rows.Count > 0 Then
For Each row As DataRow In myData.Rows
Dim dmxrow As New MXrow
ii = ii + 1
If ii = 1 Then
dmxrow.Name = "mxrow1"
myUserControls.Add(dmxrow)
Else
dmxrow.Name = "mxrow" & CStr(ii)
myUserControls.Add(dmxrow)
dmxrow.HideHeaders()
End If
If row("SuperCategory") = "Fixed" Then
dmxrow.cboMXSuperCategory.SelectedIndex = 0
Else
dmxrow.cboMXSuperCategory.SelectedIndex = 1
End If
dmxrow.txtMXCategory.Text = row("Category")
dmxrow.txtMXExpenseName.Text = row("ExpenseName")
dmxrow.cbMXStatus.Checked = row("Status")
dmxrow.btnMXAdd.Tag = CStr(ii)
dmxrow.btnMXAlter.Tag = CStr(row("ExpListID"))
dmxrow.btnMXDelete.Tag = CStr(row("ExpListID"))
If CStr(ii) = glbMiscString Then
Dim dnmxrow As New MXrow
ii = ii + 1
dnmxrow.Name = "mxrow" & CStr(ii)
myUserControls.Add(dnmxrow)
dnmxrow.HideHeaders()
dnmxrow.cboMXSuperCategory.SelectedIndex = -1
dnmxrow.txtMXCategory.Text = ""
dnmxrow.txtMXExpenseName.Text = ""
dnmxrow.btnMXAdd.Tag = "0"
dnmxrow.btnMXAdd.Text = "Enter"
dnmxrow.btnMXAlter.Enabled = False
dnmxrow.btnMXDelete.Enabled = False
dnmxrow.cbMXStatus.Checked = False
glbMiscString = ""
End If
Next
Else
Dim dmxrow As New MXrow
dmxrow.Name = "mxrow1"
Me.Controls.Add(dmxrow)
dmxrow.Left = 40
dmxrow.Top = Me.lblExpenseList.Top + 30
dmxrow.cboMXSuperCategory.SelectedIndex = -1
dmxrow.txtMXCategory.Text = ""
dmxrow.txtMXExpenseName.Text = ""
dmxrow.btnMXAdd.Tag = "0"
dmxrow.btnMXAdd.Text = "Enter"
dmxrow.btnMXAlter.Enabled = False
dmxrow.btnMXDelete.Enabled = False
dmxrow.cbMXStatus.Checked = False
End If
ii = 0
For Each dmxrow As MXrow In myUserControls
Me.Controls.Add(dmxrow)
ii = ii + 1
If ii = 1 Then
dmxrow.Left = 40
dmxrow.Top = Me.lblExpenseList.Top + 30
dmxrow.Update()
Else
dmxrow.SendToBack()
dmxrow.Left = 40
dmxrow.Top = Me.Controls("mxrow" & CStr(ii - 1)).Bottom - 30
dmxrow.Update()
End If
Next
Dim resettop = Me.Controls("mxrow" & CStr(ii)).Bottom
Dim btnMXReset As New Button
btnMXReset.Name = "btnMXReset"
Me.Controls.Add(btnMXReset)
btnMXReset.Text = "Reset"
btnMXReset.BackColor = Color.White
btnMXReset.Left = (Me.Width / 2) - (btnMXReset.Width / 2)
btnMXReset.Top = resettop + 15
AddHandler btnMXReset.Click, AddressOf btnMXReset_Clicked
resettop = btnMXReset.Bottom + 15
Dim btnMXClose As New Button
btnMXClose.Name = "btnMXClose"
Me.Controls.Add(btnMXClose)
btnMXClose.Text = "Close"
btnMXClose.BackColor = Color.White
btnMXClose.Left = (Me.Width / 2) - (btnMXClose.Width / 2)
btnMXClose.Top = resettop
AddHandler btnMXClose.Click, AddressOf btnMXClose_Clicked
resettop = btnMXClose.Bottom + 15
Dim lblspacer As New Label
Me.Controls.Add(lblspacer)
lblspacer.Text = ""
lblspacer.Left = (Me.Width / 2) - (lblspacer.Width / 2)
lblspacer.Top = resettop
Finally
Me.ResumeLayout(True)
Application.DoEvents()
End Try
End Sub
Function GetExpenseListData() As DataTable
Dim dtt As New DataTable
Using cn As New SqlConnection(glbLocalCnxnString)
Dim cmd As New SqlCommand("SELECT SuperCategory, Category, ExpenseName, Status, ExpListID FROM ExpenseList ORDER BY Supercategory, Category, ExpenseName", cn)
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader
dtt.Load(dr)
End Using
End Using
Return dtt
End Function
Public Sub btnMXReset_Clicked()
Me.SuspendLayout()
For Each mxrow As MXrow In myUserControls
Me.Controls.Remove(mxrow)
Next
Me.ResumeLayout(True)
Application.DoEvents()
For Each mxrow As MXrow In myUserControls
mxrow.Dispose()
Next
myUserControls.Clear()
If glbMiscString = "" Then
Me.Controls("btnMXReset").Dispose()
Me.Controls("btnMXClose").Dispose()
End If
mdgExpListMgr_Load(Nothing, Nothing)
Me.ScrollControlIntoView(pbExpListBackground)
End Sub
ASKER
This is further to my initial post. It appears the Dialog Box's load handler is being run more than once when an "Add" button is pressed. The crash occurs after the first execution of the load handler.
My code is now slightly changed, to prevent flickering of controls when pressing the Reset button (this control simply refreshes the Dialog Box from the DB). I'll upload the new code as soon as someone responds.
My code is now slightly changed, to prevent flickering of controls when pressing the Reset button (this control simply refreshes the Dialog Box from the DB). I'll upload the new code as soon as someone responds.
ASKER
Hi Code Cruiser,
Thanks so much for dropping by.
The basic setup is that my main application window has a button to pop a Dialog Box. The Dialog Box is populated with about 200 User Controls, each containing data from a row in a DB table. Each User Control contains a dropdown, two textboxes, and a checkbox with the data from the DB table, and three buttons:
Add - Insert a "blank" User Control on the Dialog Box to add a new row to the table (this creates a User Control where the Add button is an "Enter" button).
Alter - First the user changes information in the data input controls, and then presses the Alter button to change that row on the DB table.
Delete - Delete the corresponding row on the DB table.
As mentioned in my 10/02/11 03:56 PM, some slight changes have been made to the code to hide the dialog box when the user clicks the "Refresh" button at the bottom of the dialog popup (the idea here is to allow the user to start over if he/she makes a mistake and gets confused before committing; the Refresh button handler simply destroys all the User Controls and rebuilds them from the DB table. I was having a "flickering" issue as the User Controls were being rebuilt, so I simply hide the dialog box until it is fully repainted).
The updated code for the Dialog Box is in the code smippet below.
Thanks, Stu
Thanks so much for dropping by.
The basic setup is that my main application window has a button to pop a Dialog Box. The Dialog Box is populated with about 200 User Controls, each containing data from a row in a DB table. Each User Control contains a dropdown, two textboxes, and a checkbox with the data from the DB table, and three buttons:
Add - Insert a "blank" User Control on the Dialog Box to add a new row to the table (this creates a User Control where the Add button is an "Enter" button).
Alter - First the user changes information in the data input controls, and then presses the Alter button to change that row on the DB table.
Delete - Delete the corresponding row on the DB table.
As mentioned in my 10/02/11 03:56 PM, some slight changes have been made to the code to hide the dialog box when the user clicks the "Refresh" button at the bottom of the dialog popup (the idea here is to allow the user to start over if he/she makes a mistake and gets confused before committing; the Refresh button handler simply destroys all the User Controls and rebuilds them from the DB table. I was having a "flickering" issue as the User Controls were being rebuilt, so I simply hide the dialog box until it is fully repainted).
The updated code for the Dialog Box is in the code smippet below.
Thanks, Stu
Imports System.Windows.Forms
Imports System.Data.SqlClient
Public Class mdgExpListMgr
Private myUserControls As New List(Of MXrow)
Private Sub mdgExpListMgr_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
Me.SuspendLayout()
Me.BackgroundImage = Nothing
pbExpListBackground.SendToBack()
Me.Hide()
Application.DoEvents()
Using myLoadingForm As New LoadingForm(AddressOf LoadMyFormControls)
myLoadingForm.ShowDialog(Me)
End Using
Me.Show()
Finally
Me.ResumeLayout(True)
Application.DoEvents()
End Try
End Sub
Sub LoadMyFormControls(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myForm As mdgExpListMgr = sender
Dim myData As DataTable = GetExpenseListData()
Dim ii As Integer = 0
If myData.Rows.Count > 0 Then
For Each row As DataRow In myData.Rows
Dim dmxrow As New MXrow
ii = ii + 1
If ii = 1 Then
dmxrow.Name = "mxrow1"
myUserControls.Add(dmxrow)
Else
dmxrow.Name = "mxrow" & CStr(ii)
myUserControls.Add(dmxrow)
dmxrow.HideHeaders()
End If
If row("SuperCategory") = "Fixed" Then
dmxrow.cboMXSuperCategory.SelectedIndex = 0
Else
dmxrow.cboMXSuperCategory.SelectedIndex = 1
End If
dmxrow.txtMXCategory.Text = row("Category")
dmxrow.txtMXExpenseName.Text = row("ExpenseName")
dmxrow.cbMXStatus.Checked = row("Status")
dmxrow.btnMXAdd.Tag = CStr(ii)
dmxrow.btnMXAlter.Tag = CStr(row("ExpListID"))
dmxrow.btnMXDelete.Tag = CStr(row("ExpListID"))
If CStr(ii) = glbMiscString Then
Dim dnmxrow As New MXrow
ii = ii + 1
dnmxrow.Name = "mxrow" & CStr(ii)
myUserControls.Add(dnmxrow)
dnmxrow.HideHeaders()
dnmxrow.cboMXSuperCategory.SelectedIndex = -1
dnmxrow.txtMXCategory.Text = ""
dnmxrow.txtMXExpenseName.Text = ""
dnmxrow.btnMXAdd.Tag = "0"
dnmxrow.btnMXAdd.Text = "Enter"
dnmxrow.btnMXAlter.Enabled = False
dnmxrow.btnMXDelete.Enabled = False
dnmxrow.cbMXStatus.Checked = False
glbMiscString = ""
End If
Next
ii = 0
For Each dmxrow As MXrow In myUserControls
myForm.Controls.Add(dmxrow)
ii = ii + 1
If ii = 1 Then
dmxrow.Left = 40
dmxrow.Top = myForm.lblExpenseList.Top + 30
dmxrow.Update()
Else
dmxrow.SendToBack()
dmxrow.Left = 40
dmxrow.Top = myForm.Controls("mxrow" & CStr(ii - 1)).Bottom - 30
dmxrow.Update()
End If
Next
Else
Dim dmxrow As New MXrow
dmxrow.Name = "mxrow1"
myForm.Controls.Add(dmxrow)
dmxrow.Left = 40
dmxrow.Top = myForm.lblExpenseList.Top + 30
dmxrow.cboMXSuperCategory.SelectedIndex = -1
dmxrow.txtMXCategory.Text = ""
dmxrow.txtMXExpenseName.Text = ""
dmxrow.btnMXAdd.Tag = "0"
dmxrow.btnMXAdd.Text = "Enter"
dmxrow.btnMXAlter.Enabled = False
dmxrow.btnMXDelete.Enabled = False
dmxrow.cbMXStatus.Checked = False
End If
Dim resettop = myForm.Controls("mxrow" & CStr(ii)).Bottom
Dim btnMXReset As New Button
btnMXReset.Name = "btnMXReset"
myForm.Controls.Add(btnMXReset)
btnMXReset.Text = "Reset"
btnMXReset.BackColor = Color.White
btnMXReset.Left = (myForm.Width / 2) - (btnMXReset.Width / 2)
btnMXReset.Top = resettop + 15
AddHandler btnMXReset.Click, AddressOf btnMXReset_Clicked
resettop = btnMXReset.Bottom + 15
Dim btnMXClose As New Button
btnMXClose.Name = "btnMXClose"
myForm.Controls.Add(btnMXClose)
btnMXClose.Text = "Close"
btnMXClose.BackColor = Color.White
btnMXClose.Left = (myForm.Width / 2) - (btnMXClose.Width / 2)
btnMXClose.Top = resettop
AddHandler btnMXClose.Click, AddressOf btnMXClose_Clicked
resettop = btnMXClose.Bottom + 15
Dim lblspacer As New Label
myForm.Controls.Add(lblspacer)
lblspacer.Text = ""
lblspacer.Left = (myForm.Width / 2) - (lblspacer.Width / 2)
lblspacer.Top = resettop
End Sub
Function GetExpenseListData() As DataTable
Dim dtt As New DataTable
Using cn As New SqlConnection(glbLocalCnxnString)
Dim cmd As New SqlCommand("SELECT SuperCategory, Category, ExpenseName, Status, ExpListID FROM ExpenseList ORDER BY Supercategory, Category, ExpenseName", cn)
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader
dtt.Load(dr)
End Using
End Using
Return dtt
End Function
Public Sub btnMXReset_Clicked()
Me.SuspendLayout()
For Each mxrow As MXrow In myUserControls
Me.Controls.Remove(mxrow)
Next
Me.ResumeLayout(True)
Application.DoEvents()
For Each mxrow As MXrow In myUserControls
mxrow.Dispose()
Next
myUserControls.Clear()
If Not IsNothing(Me.Controls("btnMXReset")) Then
Me.Controls("btnMXReset").Dispose()
End If
If Not IsNothing(Me.Controls("btnMXReset")) Then
Me.Controls("btnMXClose").Dispose()
End If
mdgExpListMgr_Load(Nothing, Nothing)
Me.ScrollControlIntoView(pbExpListBackground)
End Sub
Private Sub btnMXClose_Clicked()
Me.Close()
End Sub
End Class
Hi. Again, the code for Add button is missing. Also show us a screenshot of the form.
ASKER
Hi Code Cruiser,
A screen pic of the Dialog Box is attached. Each row on the Dialog Box is an instance of the User Control.
The handler for the UserControl Add button is effectively:
glbMiscString = btnMXAdd.Tag
mdgExpListMgr.btnMXReset_C licked()
(I say "effectively" as I am omitting the "Enter" portion of the logic here, as it is not pertinent to this ticket).
Stu
A screen pic of the Dialog Box is attached. Each row on the Dialog Box is an instance of the User Control.
The handler for the UserControl Add button is effectively:
glbMiscString = btnMXAdd.Tag
mdgExpListMgr.btnMXReset_C
(I say "effectively" as I am omitting the "Enter" portion of the logic here, as it is not pertinent to this ticket).
Stu
If I'm following you.... you need to add the "WithEvents" keyword when you instaniate your custom controls.
http://msdn.microsoft.com/en-us/library/aty3352y(v=VS.100).aspx
For example:
Dim WithEvents dmxrow As New MXrow
http://msdn.microsoft.com/en-us/library/aty3352y(v=VS.100).aspx
For example:
Dim WithEvents dmxrow As New MXrow
May be I am missing something but how does setting the
glbMiscString = btnMXAdd.Tag
is supposed to insert an empty row?
glbMiscString = btnMXAdd.Tag
is supposed to insert an empty row?
ASKER
graye - Will check out your link.
CodeCruiser - glbMiscString is a global string variable declared in a Standard Module. The load handler for the Dialog Box creates a "blank" User Control in the position designated by glbMiscString (actually just after it) for creation of a new DB table row (the "Add" button for the blank User Control is labeled "Enter"). The idea is that the non-blank User Controls are used to alter or delete existing table rows, but a blank User Control is used to add a new table row. When the "Add" button on a User Control is pressed, the intent is for the Dialog Box to refresh with a blank User Control just after the one containing the pressed "Add" button.
CodeCruiser - glbMiscString is a global string variable declared in a Standard Module. The load handler for the Dialog Box creates a "blank" User Control in the position designated by glbMiscString (actually just after it) for creation of a new DB table row (the "Add" button for the blank User Control is labeled "Enter"). The idea is that the non-blank User Controls are used to alter or delete existing table rows, but a blank User Control is used to add a new table row. When the "Add" button on a User Control is pressed, the intent is for the Dialog Box to refresh with a blank User Control just after the one containing the pressed "Add" button.
ASKER
graye - Link merely confirms that you can assign event handlers to variables. Control buttons like the "Add" buttons are natively supplied with event handling capability, in this case the operant one being the Click event.
An alternate solution would be to eliminate the "Add" buttons, and just always provide a "blank" "Enter" type UserControl at the top or bottom of the form. This would require an hour or so of recoding, so I'm hoping to avoid this. Also, I don't know if it will help, as the recursion problem may persist after making the changes.
The real question is: why is the DialogBox load handler recursing in the first place after mdgExpListMgr.btnMXReset_C licked() (the Reset button handler in the DialogBox) is invoked from the UserControl Add button handler? The DialogBox load handler does not recourse on initial popup of the DialogBox, nor on pressing the Reset button on the DialogBox. It only recurses when the DialogBox's Reset button handler is invoked from the UserControl class.
An alternate solution would be to eliminate the "Add" buttons, and just always provide a "blank" "Enter" type UserControl at the top or bottom of the form. This would require an hour or so of recoding, so I'm hoping to avoid this. Also, I don't know if it will help, as the recursion problem may persist after making the changes.
The real question is: why is the DialogBox load handler recursing in the first place after mdgExpListMgr.btnMXReset_C
Did you step through the code to see what code is executing when the add button is pressed?
ASKER
CodeCruiser,
No, not yet. Just placed a few message boxes in the DialogBox load handler to confirm the recursion. I could make a copy of the DB table and step through the code with a much smaller table (say 2-3 rows), as stepping through now would take forever (200 rows). I'll try that and report back.
Thanks, Stu
No, not yet. Just placed a few message boxes in the DialogBox load handler to confirm the recursion. I could make a copy of the DB table and step through the code with a much smaller table (say 2-3 rows), as stepping through now would take forever (200 rows). I'll try that and report back.
Thanks, Stu
ASKER
CodeCruiser,
I did some detailed debugging by stepping through the code. Please see the updated Load handler for the DialogBox in the code snippet section.
The DialogBox Load handler works perfectly when I pop the dialog, as well as when I press the Refresh button on the DialogBox (this simply disposes all controls on the DialogBox rebuilds them using a DB table (most of the controls are UserControls containing data from a DB table)).
The crash occurs when I try to run the "Enter" logic on a blank UserControl (this permits entry of a new record into the DB table using logic in the UserControl's back end code). Look at the code snippet, and observe the line that says "Me.Show()". As expected, mdgExpListMgr_Load (the Load handler for the DialogBox) runs after the UserControl creates the new DB table record (the "Enter" button handler for the UserControl executes a Sub (the Reset button handler) on the DialogBox to dispose all its controls, which in turn invokes the DialogBox Load handler so the controls can be rebuilt reflecting the table row just added). But, within the execution of the mdgExpListMgr_Load, after executing the line "Me.Show()", mdgExpListMgr_Load starts to run a second time (control goes up to the Sub declaration, and the logic starts over again). This is why I'm getting recursion, and then getting an abend (the recursion results in an index out-of-bounds error in Sub LoadMyFormControls which ends up getting called twice by mdgExpListMgr_Load).
So, the question now is: why does Sub mdgExpListMgr_Load recurse when using the "Enter" button on the UserControl (i.e., why does control jump from "Me.Show()" to the top of mdgExpListMgr_Load instead of simply continuing to the next line ("Me.Activate()"))?
Thanks, Stu
I did some detailed debugging by stepping through the code. Please see the updated Load handler for the DialogBox in the code snippet section.
The DialogBox Load handler works perfectly when I pop the dialog, as well as when I press the Refresh button on the DialogBox (this simply disposes all controls on the DialogBox rebuilds them using a DB table (most of the controls are UserControls containing data from a DB table)).
The crash occurs when I try to run the "Enter" logic on a blank UserControl (this permits entry of a new record into the DB table using logic in the UserControl's back end code). Look at the code snippet, and observe the line that says "Me.Show()". As expected, mdgExpListMgr_Load (the Load handler for the DialogBox) runs after the UserControl creates the new DB table record (the "Enter" button handler for the UserControl executes a Sub (the Reset button handler) on the DialogBox to dispose all its controls, which in turn invokes the DialogBox Load handler so the controls can be rebuilt reflecting the table row just added). But, within the execution of the mdgExpListMgr_Load, after executing the line "Me.Show()", mdgExpListMgr_Load starts to run a second time (control goes up to the Sub declaration, and the logic starts over again). This is why I'm getting recursion, and then getting an abend (the recursion results in an index out-of-bounds error in Sub LoadMyFormControls which ends up getting called twice by mdgExpListMgr_Load).
So, the question now is: why does Sub mdgExpListMgr_Load recurse when using the "Enter" button on the UserControl (i.e., why does control jump from "Me.Show()" to the top of mdgExpListMgr_Load instead of simply continuing to the next line ("Me.Activate()"))?
Thanks, Stu
Private Sub mdgExpListMgr_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.SuspendLayout()
Me.BackgroundImage = Nothing
pbExpListBackground.SendToBack()
Me.Hide()
Using myLoadingForm As New LoadingForm(AddressOf LoadMyFormControls)
myLoadingForm.ShowDialog(Me)
End Using
Me.Show()
Me.Activate()
Me.ResumeLayout(True)
End Sub
> after executing the line "Me.Show()", mdgExpListMgr_Load starts to run a second time
Why do you have the me.Show there?
Why do you have the me.Show there?
ASKER
Hi CodeCruiser,
Me.Show() simply reverses Me.Hide(). These lines were put in to hide flickering in the form as the DialogBox load handler rebuilds the UserControls from the DB table when the Refresh button, or any buttons on the UserControls, are pressed. A problem I had with this approach was that hiding the DialogBox also hid the main form, and I had to bring it back to the top with the Me.Activate() command. I've updated the code using the Visible property to prevent the loss of focus on the main app form (please see the coe snippet).
Will update on status in separate post.
Stu
Me.Show() simply reverses Me.Hide(). These lines were put in to hide flickering in the form as the DialogBox load handler rebuilds the UserControls from the DB table when the Refresh button, or any buttons on the UserControls, are pressed. A problem I had with this approach was that hiding the DialogBox also hid the main form, and I had to bring it back to the top with the Me.Activate() command. I've updated the code using the Visible property to prevent the loss of focus on the main app form (please see the coe snippet).
Will update on status in separate post.
Stu
Private Sub mdgExpListMgr_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.BackgroundImage = Nothing
pbExpListBackground.SendToBack()
Me.Visible = False
frmMain.Activate()
LoadControls(Nothing, Nothing)
Me.Visible = True
End Sub
ASKER
Hi CodeCruiser,
This is a follow-up to my previous post. I am still suffering from unexpected logic jumps. I slightly restructured the UserControl so the top one is blank (for enttering new rows into the DB table), and the rest are for altering/deleting existing rows.
I attempted to perform a record insert using the top blank UserControl. The logic in the "Enter" button handler on the UserControl added the new record, and then as desired invoked the Dialog Box's Reset handler to purge existing controls on the popup (interestingly, by invoking the UserControl handler, all these controls were automatically disposed, so maybe this step isn't necessary).
Near the end of the Reset button handler, I issue the command mdgExpListMgr_Load(Nothing , Nothing), so as to invoke the Load handler for the DialogBox, which in turn invokes Sub LoadControls (to rebuild the UserControls reflecting the row just added). The first few lines of LoadControls are shown in the code snippet.
The second line, Dim dnmxrow As New MXrow, oddly directs to the "Alter" button handler of the UserControl (even though this button is not being manually or programmatically clicked). The same result occurs when I try an "Alter" to an existing row; the row is properly altered on the DB table, but the same unexplained jump occurs at Dim dnmxrow As New MXrow to the "Alter" button handler of the UserControl.
Stu
This is a follow-up to my previous post. I am still suffering from unexpected logic jumps. I slightly restructured the UserControl so the top one is blank (for enttering new rows into the DB table), and the rest are for altering/deleting existing rows.
I attempted to perform a record insert using the top blank UserControl. The logic in the "Enter" button handler on the UserControl added the new record, and then as desired invoked the Dialog Box's Reset handler to purge existing controls on the popup (interestingly, by invoking the UserControl handler, all these controls were automatically disposed, so maybe this step isn't necessary).
Near the end of the Reset button handler, I issue the command mdgExpListMgr_Load(Nothing
The second line, Dim dnmxrow As New MXrow, oddly directs to the "Alter" button handler of the UserControl (even though this button is not being manually or programmatically clicked). The same result occurs when I try an "Alter" to an existing row; the row is properly altered on the DB table, but the same unexplained jump occurs at Dim dnmxrow As New MXrow to the "Alter" button handler of the UserControl.
Stu
Me.SuspendLayout()
Dim dnmxrow As New MXrow
dnmxrow.Name = "mxrow0"
myUserControls.Add(dnmxrow)
dnmxrow.cboMXSuperCategory.SelectedIndex = -1
dnmxrow.txtMXCategory.Text = ""
dnmxrow.txtMXExpenseName.Text = ""
dnmxrow.btnMXAlter.Text = "Enter"
dnmxrow.btnMXDelete.Enabled = False
dnmxrow.cbMXStatus.Checked = False
ASKER
Hi CodeCruiser,
I think I found the real problem. The jump to the UserControl back end when new MXRow's (UserControls) are instantiated is not an issue, as all this does is invoke the New() handler of the UserControl and perform initializations after the InitializeComponent() call.
The real issue appears to be this: the command "Me.Visible = True" is invoked in the DialogBox Load handler to "unhide" the DialogBox (after hiding it temporarily so it can paint controls quickly without flickering). "Me.Visible = True" does not reinvoke the DialogBox Load handler when the DialogBox is initially popped, or when the Reset button on the DialogBox disposes and refreshes the UserControls. But "Me.Visible = True" does cause a jump back to the start of the DialogBox Load handler when control is returned from the UserControl back end code to the DialogBox.
To make things simpler, I've integrated the code in LoadControls() into the DialogBox Load handler (Sub mdgExpListMgr_Load), so the logic for this handler is now simply:
Me.BackgroundImage = Nothing
pbExpListBackground.SendTo Back()
Me.Visible = False
frmMain.Activate()
[logic to instantiate and paint UserControls]
Me.Visible = True
Please see the code snippet for the current state of the Add/Enter button handler in the User Control, and the Reset button handler.
So, all I need to know is why Me.Visible = True causes mdgExpListMgr_Load to restart, but only in the case when mdgExpListMgr_Load is invoked after pressing a UserControl button (and not at initial DialogBox pop or DialogBox Refresh button click).
Stu
I think I found the real problem. The jump to the UserControl back end when new MXRow's (UserControls) are instantiated is not an issue, as all this does is invoke the New() handler of the UserControl and perform initializations after the InitializeComponent() call.
The real issue appears to be this: the command "Me.Visible = True" is invoked in the DialogBox Load handler to "unhide" the DialogBox (after hiding it temporarily so it can paint controls quickly without flickering). "Me.Visible = True" does not reinvoke the DialogBox Load handler when the DialogBox is initially popped, or when the Reset button on the DialogBox disposes and refreshes the UserControls. But "Me.Visible = True" does cause a jump back to the start of the DialogBox Load handler when control is returned from the UserControl back end code to the DialogBox.
To make things simpler, I've integrated the code in LoadControls() into the DialogBox Load handler (Sub mdgExpListMgr_Load), so the logic for this handler is now simply:
Me.BackgroundImage = Nothing
pbExpListBackground.SendTo
Me.Visible = False
frmMain.Activate()
[logic to instantiate and paint UserControls]
Me.Visible = True
Please see the code snippet for the current state of the Add/Enter button handler in the User Control, and the Reset button handler.
So, all I need to know is why Me.Visible = True causes mdgExpListMgr_Load to restart, but only in the case when mdgExpListMgr_Load is invoked after pressing a UserControl button (and not at initial DialogBox pop or DialogBox Refresh button click).
Stu
In back end code for UserControl
--------------------------------
Private Sub btnMXAlter_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnMXAlter.Click
Dim errtext As String = ValidateFields()
If errtext <> "" Then
frmMain.PopErrorDialog(errtext)
Exit Sub
End If
Dim CN As New SqlConnection
Dim CMD As New SqlCommand
CN.ConnectionString = glbLocalCnxnString
CN.Open()
CMD.Connection = CN
Dim SQL As String = ""
If btnMXAlter.Text = "Alter" Then
SQL = "update ExpenseList set "
SQL = SQL & "SuperCategory='" & cboMXSuperCategory.Text & "',"
SQL = SQL & "Category='" & txtMXCategory.Text & "',"
SQL = SQL & "ExpenseName='" & txtMXExpenseName.Text & "',"
SQL = SQL & "Status='" & cbMXStatus.Checked.ToString & "' "
SQL = SQL & "where ExpListID=" & btnMXAlter.Tag
Else
SQL = "insert into ExpenseList values("
SQL = SQL & "'" & cboMXSuperCategory.Text & "',"
SQL = SQL & "'" & txtMXCategory.Text & "',"
SQL = SQL & "'" & txtMXExpenseName.Text & "',"
SQL = SQL & "'" & cbMXStatus.Checked.ToString & "')"
CMD.CommandText = SQL
End If
CMD.CommandText = SQL
CMD.ExecuteNonQuery()
CN.Close()
CMD = Nothing
CN = Nothing
mdgExpListMgr.btnMXReset_Clicked()
End Sub
In back end code for DialogBox
------------------------------
Public Sub btnMXReset_Clicked()
Me.SuspendLayout()
For Each mxrow As MXrow In myUserControls
Me.Controls.Remove(mxrow)
Next
For Each mxrow As MXrow In myUserControls
mxrow.Dispose()
Next
myUserControls.Clear()
If Not IsNothing(Me.Controls("btnMXReset")) Then
Me.Controls("btnMXReset").Dispose()
End If
If Not IsNothing(Me.Controls("btnMXReset")) Then
Me.Controls("btnMXClose").Dispose()
End If
mdgExpListMgr_Load(Nothing, Nothing)
Me.ResumeLayout(True)
Me.ScrollControlIntoView(pbExpListBackground)
End Sub
To be honest, your code is not making much sense to me. May be because I am sleepy :-)
Why you need to redraw everything to add a row? Can you not just add it?
Why you need to redraw everything to add a row? Can you not just add it?
ASKER
Hi CodeCruiser,
Redraw is necessary as DB table rows can be added, altered, and deleted. The setup is that there is a blank UserControl on top of the DialogBox to add a row to the DB, and filled UserControls below for each row already on the DB (for alter/delete purposes).
Maybe you can take a another look at my last few posts after getting some sleep.
Thanks, Stu
Redraw is necessary as DB table rows can be added, altered, and deleted. The setup is that there is a blank UserControl on top of the DialogBox to add a row to the DB, and filled UserControls below for each row already on the DB (for alter/delete purposes).
Maybe you can take a another look at my last few posts after getting some sleep.
Thanks, Stu
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Needed to submit MS ticket to resolve issue.
Where is the add button control?