Question Conditionally active buttons not consistently enabled/disabled

mikoroshi

New member
Joined
Feb 4, 2014
Messages
3
Programming Experience
Beginner
A little backstory: I am working on a set of three programs to operate as a call commander for talk radio. This is a concept I'm working on to build up my skills. I'm building it with the following ideas in place: There are three computers in the studio, one where the call screener works and inputs data about the caller's name, location, and topic, the producer's computer where they control which caller is the next one to talk to, and the third is just a box for the host which tells them which caller is next and what they're calling in about.

I have my first program (the screener) up and running without issue. The screener takes down the information and logs it (to an Access db connected via SQL), and once everything is confirmed, sets them to "Air Ready." Callers logged as "Air Ready" show up in the producer's computer in a grid of buttons with the caller details. The producer clicks the button related to the caller, which disables all the other buttons in the panel and hides the button that was clicked, replacing it temporarily with three buttons that assign "Next Caller" or "Important" flags to the caller, and one to clear those flags. Based on the flag selected, the button is gray (no flag), light blue (next caller) or yellow (important caller).

I have two glitches I'd love some help with: Self-Resolved, see bottom of post: [First, is that the button to set caller on line D to "Next" is always disabled, but for all the other lines (A,B,C, W-Z etc.) it isn't.] The second, is that once in a while, all the buttons go yellow despite not having the "Important" flag assigned to them. This second issue only stays until next time the grid of buttons is refreshed before correcting itself.

Here's the code that pertains to populating these buttons and applying background colors.

This is what populates the buttons with caller information and sets background colors. Called by "Call refreshall(<1-8>)":
VB.NET:
    Private Function refreshAll(ByVal sender As Integer)
        Dim btn As Button
        Dim callerID As String ' Determines which caller's data is selected
        Dim readyforair As Integer
        Dim priorityflag As Integer
        Dim textstring As String
        Dim nextflag As Integer

        ' ------------------------------------------------------------------------------------------------------------------
        ' Prepare SQL database connection
        Dim con As New OleDb.OleDbConnection
        Dim ds As New DataSet
        Dim da As OleDb.OleDbDataAdapter
        Dim sql As String
        ' ------------------------------------------------------------------------------------------------------------------

        ' Determine which caller's data is filled in
        If sender = 1 Then
            callerID = "A"
        ElseIf sender = 2 Then
            callerID = "B"
        ElseIf sender = 3 Then
            callerID = "C"
        ElseIf sender = 4 Then
            callerID = "D"
        ElseIf sender = 5 Then
            callerID = "W"
        ElseIf sender = 6 Then
            callerID = "X"
        ElseIf sender = 7 Then
            callerID = "Y"
        ElseIf sender = 8 Then
            callerID = "Z"
        End If

        ' ------------------------------------------------------------------------------------------------------------------
        ' Establish database connection
        con.ConnectionString = "<redacted>"
        con.Open()
        sql = "SELECT * FROM Database WHERE (CallCompID = '" & callerID & "') ORDER BY ID DESC"
        da = New OleDb.OleDbDataAdapter(sql, con)
        da.Fill(ds, "Database")
        ' ------------------------------------------------------------------------------------------------------------------
        ' These have already been error check and filled in at call screener end so no fear of empty entries causing a bug
        textstring = callerID & ": " & ds.Tables(0).Rows(0).Item("CallerName") & vbNewLine & ds.Tables(0).Rows(0).Item("CallerLocation") & vbNewLine & ds.Tables(0).Rows(0).Item("CallerTopic")

        ' Determines if caller has been set as a priority by the show's producer
        priorityflag = Convert.ToInt32(ds.Tables(0).Rows(0).Item("PriorityFlag"))

        ' Determines if caller has been set as a Air Ready by a show's screener
        readyforair = Convert.ToInt32(ds.Tables(0).Rows(0).Item("AirReady"))

        ' Determines if caller has been set as Next Call by show's producer
        nextflag = Convert.ToInt32(ds.Tables(0).Rows(0).Item("NextFlag"))

        For Each btn In Me.pnlActiveCalls.Controls
            ' Caller Name fields
            If TypeOf btn Is Button Then
                Try
                    If btn.Name = ("btn" & callerID) Then
                        If priorityflag = 1 Then
                            ' Has priority
                            btn.BackColor = Color.Yellow
                        ElseIf priorityflag = 0 Then
                            ' has no priority
                            btn.BackColor = Color.LightGray
                        End If

                        If ds.Tables(0).Rows(0).Item("CallerName") = "Blank" Then
                            ' If no caller logged in database
                            btn.BackColor = Color.LightGray
                            btn.Enabled = False
                            btn.Text = "No Caller"
                            'oldtext = listComms.Text
                            'listComms.Text = strTime & ": No caller on " & callerID & vbNewLine & oldtext
                        Else
                            ' If caller logged in database:
                            If readyforair = 1 Then
                                ' If caller flagged as ready
                                btn.Enabled = True
                                btn.Text = textstring
                            ElseIf readyforair = 0 Then
                                btn.Enabled = False
                                btn.Text = "No Caller"
                            End If
                            If nextflag = 1 Then
                                ' is next caller
                                btn.BackColor = Color.LightBlue
                            ElseIf nextflag = 0 Then

                            End If
                        End If

                        If btn.Text = "No Caller" Then
                            btn.Enabled = False
                            btn.BackColor = Color.LightGray
                        End If
                    End If
                Catch
                    MsgBox("Error at fill for " & callerID)
                End Try
            End If
        Next
        ' ------------------------------------------------------------------------------------------------------------------
        ' Kill connection
        con.Close()
        ' ------------------------------------------------------------------------------------------------------------------
    End Function

And here's the code that displays those three buttons to set "Next Caller", "Important Caller" and clear the flags. Would have been called by doing "Call overwritebuttons("<A-Z>")":
VB.NET:
    Private Function overwritebuttons(ByVal sender As String)
        sourcebutton = sender ' Global variable defined elsewhere
        updateairID = sender ' Global variable defined elsewhere
        For Each btn In Me.pnlActiveCalls.Controls
            If TypeOf btn Is Button Then
                Try
                    If btn.Name <> ("btn" & sender) Then
                        ' Disables buttons that are on the panel, but this should be overwritten in the ElseIf for my three buttons
                        btn.enabled = False ' *** I think this is where the problem is but it only happens for caller D ***
                    ElseIf btn.Name = ("btn" & sender) Then
                        ' Hides source button
                        btn.enabled = False
                        btn.visible = False

                        ' Enables the three buttons
                        Me.btnNextFlag.Enabled = True
                        Me.btnPriorityFlag.Enabled = True
                        Me.btnClearFlags.Enabled = True

                        'Shows the three buttons
                        Me.btnNextFlag.Visible = True
                        Me.btnPriorityFlag.Visible = True
                        Me.btnClearFlags.Visible = True

                        ' Positioning data for source button
                        Dim math1 As Integer = Convert.ToInt32(btn.Location.X) ' Gets X position of source button
                        Dim math2 As Integer = Convert.ToInt32(btn.location.y) ' Gets Y position of source button

                        ' Positioning sequence for the three buttons
                        Me.btnNextFlag.Location = New Point(math1, math2) ' Sets btnNext to same X,Y position as source button
                        Me.btnPriorityFlag.Location = New Point((math1 + 75), math2) ' Sets btnPriorityFlag to the right of btnNext
                        Me.btnClearFlags.Location = New Point((math1 + 150), math2) ' Sets btnClearFlags to the right of btnPriorityFlag
                    End If
                Catch
                End Try
            End If
        Next
    End Function

Any help would be greatly appreciated. I'm more concerned with the "Next Caller" button not working for line D than I am about the thing where all the buttons go yellow temporarily.

UPDATE:

I changed this:
VB.NET:
If btn.Name <> ("btn" & sender) Then                         ' Disables buttons that are on the panel, but this should be overwritten in the ElseIf for my three buttons                         btn.enabled = False ' *** I think this is where the problem is but it only happens for caller D ***

to this:
VB.NET:
If btn.Name <> ("btn" & sender) Then
                        ' Disables buttons that are on the panel, but this should be overwritten in the ElseIf for my three buttons

                        If btn.name = "btnNextFlag" Then
                            btn.Enabled = True
                        ElseIf btn.name = "btnPriorityFlag" Then
                            btn.enabled = True
                        ElseIf btn.name = "btnClearFlags" Then
                            btn.enabled = True
                        Else
                            btn.enabled = False ' *** I think this is where the problem is but it only happens for caller D ***
                        End If

and it appears to have fixed my random disabled button issue. I am still having the issue where they all go yellow for a little while.
 
Last edited:
If the Buttons are turning yellow it's because your code is setting them that colour. Start by placing a breakpoint on the line that does so and then execution will break at that point. You can then examine the state of the application and hopefully see why execution made its way to that line unexpectedly. If not then your debugging will need to go deeper, setting a breakpoint higher in the code and stepping through it line by line and checking the state at each step. If at any point a variable holds an unexpected value or execution takes and unexpected direction then you have found an issue and can determine why based on the current state of the running app, not by looking over static code.
 
That was extremely helpful. I found the issue is that PriorityFlag is a global variable, and it's not clearing once the buttons are populated. So it tells all the buttons to go yellow! I need to rejigger how it determines what caller has a PriorityFlag, since just clearing it back to 0 will mean a caller that is priority will not be yellow any more, hah. Thanks!
 
By adding a PriorityFlag = 0 line immediately after the If...Then... part that changes the btn.BackColor = color.Yellow, it appears fixed.
 
Learning to debug effectively is one of the most important lessons a beginner programmer can learn. If simply reading code was enough to find all the issues then we wouldn't make the mistakes in the first place. :) It's disappointing how many programming courses and books neglect to even mention it, never mind show how to perform it. They tell you how to write code but not how to fix the mistakes that unavoidably occur.
 
Back
Top