Question Problem Accessing Property of Custom Class

ent_ttu

Member
Joined
Jun 17, 2008
Messages
14
Programming Experience
1-3
I've got a need to create a custom list box, prepopulated with names from a database. I wrote a class to do that, called rpListBox, which inherits listbox. Here's the class:

VB.NET:
Public Class rpListBox
    Inherits System.Windows.Forms.ListBox
    Dim con As New OleDb.OleDbConnection
    Dim ds As New DataSet
    Dim da As OleDb.OleDbDataAdapter
    Dim inc As Integer
    Dim lstRespParty As New ListBox
    Dim MaxRows As Integer
    Dim resp As responsibleParty
    Dim rpSQL As String

    Public Sub New(ByVal ParentForm As Control, ByVal intXAxis As Integer, ByVal intYAxis As Integer)
        Dim people As New ArrayList()

        con.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = C:\barcode_inventory.mdb"
        con.Open()

        rpSQL = "select first_name, last_name, person_id from person where status = 'a' order by last_name"

        da = New OleDb.OleDbDataAdapter(rpSQL, con)
        da.Fill(ds, "ppl")


        MaxRows = ds.Tables("ppl").Rows.Count
        inc = 0

        Do While inc < MaxRows
            resp = New responsibleParty(ds.Tables("ppl").Rows(inc).Item("person_id"))
            people.Add(resp)
            inc = inc + 1
        Loop


        lstRespParty.DataSource = people

        lstRespParty.DisplayMember = "rpLastNameFirst"
        lstRespParty.ValueMember = "personNo"

        'specify size
        lstRespParty.Size = New System.Drawing.Size(400, 100)

        'specify location of box.  currently set for frmEdit, but will need to be changed to set for whatever form is being used
        lstRespParty.Location = New System.Drawing.Point(intXAxis, intYAxis)

        ParentForm.Controls.Add(lstRespParty)
    End Sub

    Public Property selectedPerson() As String
        Get
            Return lstRespParty.SelectedValue
        End Get
        Set(ByVal value As String)
            lstRespParty.SelectedValue = value
        End Set
    End Property

End Class

On a windows form, I get a list of items from a database (it varies each time the page is loaded), and display the description of the item, with an instance of rpListBox for each individual item. (This page will be used to change the person for each individual item.) I use a loop to assign the name of each rpListBox based on the primary key for the item in that row.

When they save the form, I want to loop through each row and determine if the person was changed, and get the value of the new person. Code for the form is here:

VB.NET:
Public Class frmChangeRP
    Dim aryOldRP As New ArrayList()
    Dim btnNewCancel As New Button
    Dim btnUpdateRP As New Button
    Dim con As New OleDb.OleDbConnection
    Dim da As OleDb.OleDbDataAdapter
    Dim ds As New DataSet
    Dim intMaxRows As Integer
    Dim strInvByLocSQL As String
    Dim strLocation As String
    Private Sub frmChangeRP_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'show input box to allow user to tell us the location for which they want to change the responsible party
        strLocation = InputBox("Enter a location: ", "Location")

        Dim tlpInvItems = New System.Windows.Forms.TableLayoutPanel
        Me.Controls.Add(tlpInvItems)

        'query db for all items in provided location
        strInvByLocSQL = "select tag_number, description, person_id from asset where location = '" & strLocation & "';"

        con.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = C:\barcode_inventory.mdb"
        con.Open()

        da = New OleDb.OleDbDataAdapter(strInvByLocSQL, con)
        da.Fill(ds, "items")

        intMaxRows = ds.Tables("items").Rows.Count
        'declare array to hold all the items

        tlpInvItems.ColumnCount = 2
        tlpInvItems.RowCount = intMaxRows
        tlpInvItems.autosize = True

        tlpInvItems.Location = New System.Drawing.Point(300, 350)

        For recordIndex As Integer = 0 To intMaxRows - 1
            Dim lbl As New Label
            Dim tag As String

            tag = ds.Tables("items").Rows(recordIndex).Item("tag_number")
            Dim invItem As New inventoryItem(tag)
            lbl.Text = ds.Tables("items").Rows(recordIndex).Item("tag_number") & " - " & ds.Tables("items").Rows(recordIndex).Item("description")
            lbl.AutoSize = True

            tlpInvItems.Controls.Add(lbl)

            Dim lstRespParty As New rpListBox(tlpInvItems, 352, 450)
            lstRespParty.Name = "rp" & String.Format("{0:00000}", tag)
            lstRespParty.selectedPerson = invItem.responsibleID

            'populate arraylist to hold old name to use for comparison
            aryOldRP.Add(invItem)
        Next

        'add buttons at bottom of form b/c don't know how long the table will be
        'set size and text of buttons and event handlers
        btnUpdateRP.Size = New System.Drawing.Size(173, 42)
        btnUpdateRP.Text = "Update"
        btnUpdateRP.UseVisualStyleBackColor = True
        AddHandler btnUpdateRP.Click, AddressOf Me.btnUpdateRP_Click

        btnNewCancel.Size = New System.Drawing.Size(173, 42)
        btnNewCancel.Text = "Cancel"
        btnNewCancel.UseVisualStyleBackColor = True
        AddHandler btnNewCancel.Click, AddressOf Me.btnCancel_Click

        tlpInvItems.Controls.Add(btnUpdateRP)
        tlpInvItems.Controls.Add(btnNewCancel)
    End Sub


    Private Sub btnUpdateRP_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim invItem As inventoryItem
        For Each invItem In aryOldRP
            'check appropriate list box for "new" responsible party value
            Dim strRPName As String
            Dim strNewRPVal As String

            strRPName = "rp" & String.Format("{0:00000}", invItem.tagNumber)
            'try and get value in named textbox
            strNewRPVal = FindControl(strRPName, Me).selectedPerson()

            MsgBox("name is: " & strRPName)

            MsgBox("new person: " & strNewRPVal)
        Next
    End Sub

    Private Function FindControl(ByVal ControlName As String, ByVal CurrentControl As Control) As Control
        'this code copied from internet; it actually works!
        For Each ctr As Control In CurrentControl.Controls
            If ctr.Name = ControlName Then
                Return ctr
            Else
                ctr = FindControl(ControlName, ctr)
                If Not ctr Is Nothing Then
                    Return ctr
                End If
            End If
        Next
    End Function
End Class

I am getting an error that reads "'selectedPerson' is not a member of 'system.windows.forms.control'." on the line that reads
VB.NET:
strNewRPVal = FindControl(strRPName, Me).selectedPerson()

Isn't a listbox a control? Since I inherited listbox, why can't it see the selectedPerson property I created?

I'm obviously missing something. Any suggestions would be appreciated.

TIA!
 
Type cast problem, FindControl returns an object of type Control, the Control class does not have a selectedPerson member, cast that control object to type rpListBox and you can access the selectedPerson member. Do this by using CType or DirectCast operators.
VB.NET:
Dim rp As rpListBox = CType(thecontrol, rpListBox)
 
Thanks for the response!

I'm not sure I understand where to put the code you suggested... I made changes as follows:
VB.NET:
Dim ctlNewRPVal As Control

ctlNewRPVal = FindControl(strRPName, Me)

Dim rp As rpListBox = CType(ctlNewRPVal, rpListBox)

I have a messagebox giving me the right name for strRPName, but when I try to access any property of rp, I get an "object reference not set to instance of an object" error.

Does that mean findcontrol isn't working right? If not, how can I fix it?

Thanks again!
 
Why not access it directly in the containing Controls collection by name index, like Panel1.Controls(strRPName). Or if you have these listboxes in different containers research GetNextControl method.
 
Thanks again for the response. I just found out that the part of the project that I was using this for has been removed, so I don't need this functionality at this time.

However, if I ever have to go back and get this part working again (which I'm sure I will, eventually), I'll definately check out your suggestions.

Thanks again!
 
Back
Top