Link to home
Start Free TrialLog in
Avatar of stuengelman
stuengelmanFlag for United States of America

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_Clicked()

(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

Open in new window

Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

>Pressing an "Add" button on a UserControl

Where is the add button control?
Avatar of stuengelman

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.
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
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

Open in new window

Hi. Again, the code for Add button is missing. Also show us a screenshot of the form.
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_Clicked()

(I say "effectively" as I am omitting the "Enter" portion of the logic here, as it is not pertinent to this ticket).

Stu User generated image
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
May be I am missing something but how does setting the

glbMiscString = btnMXAdd.Tag

is supposed to insert an empty row?
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.
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_Clicked() (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.
Did you step through the code to see what code is executing when the add button is pressed?
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
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
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

Open in new window

> after executing the line "Me.Show()", mdgExpListMgr_Load starts to run a second time

Why do you have the me.Show there?
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
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

Open in new window

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
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

Open in new window

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.SendToBack()
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

Open in new window

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?
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
ASKER CERTIFIED SOLUTION
Avatar of stuengelman
stuengelman
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Needed to submit MS ticket to resolve issue.