tags:

views:

321

answers:

2

Not sure exactly what I need to do to make this work, so my description may be lacking at first. Essentially I am writing a program launcher that recreates itself each time on load. It pulls the data regarding the tabs and buttons from an SQLite database and builds itself dynamically at run time. I get my problem when I pass the tab name through to the function that creates the buttons. I need the name to pull the right set of buttons from the database and I then tried to use the name to place the buttons on the right tab when I create them, but the debugger calls it a null reference because it doesn't point correctly to the tabpage that I'm trying to make it point to (at least that is what I'm guessing). Any ideas on how to make this work right?

Private Sub CreateTabs()
    Dim SQLconnect As New SQLite.SQLiteConnection()
    Dim SQLcommand As SQLiteCommand
    SQLconnect.ConnectionString = "Data Source=" & sPath & "\dock.db;"
    SQLconnect.Open()
    SQLcommand = SQLconnect.CreateCommand
    SQLcommand.CommandText = "SELECT title FROM tabs"
    Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
    Dim Tabs(25) As String
    Dim c As Integer = 1
    While SQLreader.Read()
        Tabs(c) = SQLreader(0)
        c = c + 1
    End While
    SQLcommand.Dispose()
    SQLconnect.Close()
    For i = 1 To UBound(Tabs)
        If Tabs(i) <> "" Then
            Launcher.TabPages.Add(Tabs(i))
            CreateButtons(Tabs(i))
        End If
    Next
End Sub

Private Sub CreateButtons(ByVal tab)
    Dim SQLconnect As New SQLite.SQLiteConnection()
    Dim SQLcommand As SQLiteCommand
    SQLconnect.ConnectionString = "Data Source=" & sPath & "\dock.db;"
    SQLconnect.Open()
    SQLcommand = SQLconnect.CreateCommand
    SQLcommand.CommandText = "SELECT id,name,path FROM buttons WHERE tab = '" & tab & "'"
    Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
    While SQLreader.Read()
        For i = 1 To 9
            Dim NewButton(i) As Button
            If Not SQLreader(2) Is System.DBNull.Value Then
                Dim myIcon As System.Drawing.Icon = Icon.ExtractAssociatedIcon(SQLreader(2))
            End If
            Dim toolTip1 As ToolTip = New System.Windows.Forms.ToolTip(Me.components)
            Me.Controls(tab).tabpages.add(NewButton(i)) '<--this causes my problem
            'NewButton(i).Width = 32
            'NewButton(i).Height = 32
            'NewButton(i).Text = i
            'NewButton(i).Image = myIcon.ToBitmap
            'If Not SQLreader(1) Is System.DBNull.Value Then
            'toolTip1.SetToolTip(NewButton(i), SQLreader(1))
            'toolTip1.Active = True
            'End If
        Next
    End While
    SQLcommand.Dispose()
    SQLconnect.Close()
End Sub
A: 

I think you've got two problems here:

  • You're trying to find the tab control by the tab name. You should instead find the tab control itself (or pass it in) and find the name of the tab inside that control. Otherwise you're trying to add a button to a collection of tab pages, instead of to a specific tab.

  • You're never actually creating a new button. You're creating an array of buttons for every iteration of the loop, but not a new actual Button object. Admittedly that doesn't jibe with your suspicion that it's due to tab pages, but it's certainly a problem...

I suspect you want this as your loop (where tabControl is the TabControl passed in):

While SQLreader.Read()
    For i = 1 To 9
        If Not SQLreader(2) Is System.DBNull.Value Then
            Dim myIcon As Icon = Icon.ExtractAssociatedIcon(SQLreader(2))
        End If
        Dim toolTip1 As ToolTip = New ToolTip(Me.components)
        Dim NewButton As Button = New Button
        NewButton.Width = 32
        NewButton.Height = 32
        NewButton.Text = i
        NewButton.Image = myIcon.ToBitmap
        tabControl.TabPages(tab).Controls.Add(NewButton)
        If Not SQLreader(1) Is System.DBNull.Value Then
            toolTip1.SetToolTip(NewButton, SQLreader(1))
            toolTip1.Active = True
        End If
    Next
End While

Hopefully that's right - my VB.NET isn't great...

I'm surprised your original code compiled though - do you have Option Strict on?

You should also use a Using statement for your command and connection so they get disposed even when an exception occurs.

Jon Skeet
it didn't compile, and still doesn't with that change. I still get the same error in debug mode "Object variable or With block variable not set." in reference to the same line.
MaQleod
If it didn't compile then how could you see anything in the debugger? You can't debug without running it, and you can't run it without compiling it. What are you passing in as `tabControl` with my change?
Jon Skeet
I just hit start debugging, and it attempts the compile and provides me the error.I am passing two arguments now, tabcontrol is the tab control name and tab is the tabpage text so that I can qualify the SQL statement correctly to select the right button set. I get the error: "Object variable or With block variable not set." on the line that attempts to add the new button to the tab, tabControl.tabpages(tab).add(NewButton)
MaQleod
Maybe this will make more sense as to what I need. This is essentially what I am looking to do: tab.Controls.add(NewButton)except that with the way I pass tab it is a string and not a reference to the object instance of the tabpage that is titled by that particular string each time it is passed. I don't know how to reference that object instance and pass it into the function.
MaQleod
If you pass in the right control for `tabControl` - *not* the name, but the actual control containing the tab pages - it should be fine.
Jon Skeet
A: 

Thanks for the help, but I found my answer. Apparently I just needed to reference the index of the tab like so:

Private Sub CreateTabs()
    Dim SQLconnect As New SQLite.SQLiteConnection()
    Dim SQLcommand As SQLiteCommand
    SQLconnect.ConnectionString = "Data Source=" & sPath & "\dock.db;"
    SQLconnect.Open()
    SQLcommand = SQLconnect.CreateCommand
    SQLcommand.CommandText = "SELECT title FROM tabs"
    Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
    Dim Tabs(25) As String
    Dim c As Integer = 1
    While SQLreader.Read()
        Tabs(c) = SQLreader(0)
        c = c + 1
    End While
    SQLcommand.Dispose()
    SQLconnect.Close()
    For i = 1 To UBound(Tabs)
        If Tabs(i) <> "" Then
            Launcher.TabPages.Add(Tabs(i))
            CreateButtons(Tabs(i), i - 1)
        End If
    Next
End Sub

Private Sub CreateButtons(ByVal tab, ByVal TabIndex)
    Dim SQLconnect As New SQLite.SQLiteConnection()
    Dim SQLcommand As SQLiteCommand
    SQLconnect.ConnectionString = "Data Source=" & sPath & "\dock.db;"
    SQLconnect.Open()
    SQLcommand = SQLconnect.CreateCommand
    SQLcommand.CommandText = "SELECT id,name,path FROM buttons WHERE tab = '" & tab & "'"
    Dim SQLreader As SQLiteDataReader = SQLcommand.ExecuteReader()
    While SQLreader.Read()
        For i = 1 To 9
            Dim NewButton As New Button
            Launcher.TabPages.Item(TabIndex).Controls.add(NewButton)
            NewButton.Width = 32
            NewButton.Height = 32
            NewButton.Location = New Point(10 + (SQLreader(0) * 32) + 10, 10)
            NewButton.Text = SQLreader(0)
            If Not SQLreader(2) Is System.DBNull.Value Then
                Dim toolTip1 As ToolTip = New System.Windows.Forms.ToolTip(Me.components)
                Dim myIcon As System.Drawing.Icon = Icon.ExtractAssociatedIcon(SQLreader(2))
                NewButton.Image = myIcon.ToBitmap
                toolTip1.SetToolTip(NewButton, SQLreader(1))
                toolTip1.Active = True
            End If
        Next
    End While
    SQLcommand.Dispose()
    SQLconnect.Close()
End Sub
MaQleod