Results 1 to 12 of 12

Thread: [RESOLVED] UserControl Question

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Apr 2007
    Posts
    197

    Resolved [RESOLVED] UserControl Question

    Hi all

    Description of problem: I have a simple form with a usercontrol on it. There is a drop down box with a list of departments in it and a button, this is all in the usercontrol. I pick a department then press the button to view the employees in a listview for the department picked. All worked fine until I moved the code for drop down and button into the usercontrol from the form.

    The data is taken from oracle database express 10G edition and I am using a cursor package (CP) and I pass parameters from the code to the oracle procedure within the CP. One of these parameters is the selected department from the drop down list (which I have picked) and my code does not seem to be picking up this parameter, it keps saying that the bold bit of code below is nothing:

    Code:
    myCmd.Parameters.Add(New OracleParameter("n_dept", OracleDbType.Varchar2)).Value = usr1.cmbDepartments.SelectedItem
    Everything else seems to be fine. Because it is not picking up the selected item then the dr.read (no data by the looks of it) is false and it just falls out without populating any employees for that dept in the listview.

    Does anyone care to take a stab at suggesting what might be wrong? Why won't it pick up the selected item in the user control I have just picked it in?

    Thanks

    G
    Last edited by Grifter; Aug 25th, 2010 at 03:46 PM.

  2. #2
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: UserControl Question

    Because an item isn't selected? That's the only reason SelectedItem would ever be Nothing (unless, of course, you've added Nothing values to your ComboBox). Maybe check SelectedIndex, too.

  3. #3
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: UserControl Question

    If you moved this code into the usercontrol then surely you dont need to say usr1.cmbDepartments but just cmbDepartments ? Do you have a public instances called usr1 that is not the one in question?

  4. #4
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: UserControl Question

    I think he's referencing the ComboBox from the form, not the UserControl. By default, the scope for added controls is Friend in VB.NET, Private in C#.

  5. #5
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: UserControl Question

    Quote Originally Posted by Grifter View Post
    I pick a department then press the button to view the employees in a listview for the department picked.
    You sure? the button is on the usercontrol.

  6. #6
    Stack Overflow mod​erator
    Join Date
    May 2008
    Location
    British Columbia, Canada
    Posts
    2,824

    Re: UserControl Question

    That would make the code impossible to build, though - UserControls don't have default instances.

  7. #7
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: UserControl Question

    Thats why I went for the public instance being declared but not being used in this case hence the nothing

  8. #8
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,422

    Re: UserControl Question

    so is the query within the usercontrol or in the parent form?

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Apr 2007
    Posts
    197

    Re: UserControl Question

    Finding it hard deciding who too respoond to first. What I will do is post the code from the different classes etc and see if anyone can see the issue:

    User control class:

    Code:
    Public Class UserControl1
        Dim emp As New employees
    
    
        Private Sub btn1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles btn1.Click
            With cmbDepartments
                If .SelectedItem Is Nothing Then
                    MessageBox.Show("Please Pick a Department Before Continuing.", "Pick Department")
                    .Focus()
                Else
                    Form1.ListView1.Items.Clear()
                    Form1.SetListViewColumns()
                    emp.getEmployeeDetails() ' Changed 19/05/2010
                End If
            End With
        End Sub
    
        Private Sub UserControl1_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles Me.Load
            Dim queryStr1 As String = "Select department_name from departments"
            'Dim queryStr2 As String = "Select department_id from departments"
            Me.connectToOra(queryStr1)
        End Sub
    
        ' Pass cmbbox, sql query string, table column, and connection string to db, for this function
        ' Use function to dimension array
        ' to dimension count for array
        ' to dimension connection as new oracle connection
        ' Associate parameter function connstr string value with oracle connection object
        ' Fire 'try' statement to firstly connect to DB with error handling
        ' Finish 'try' then dimension a new oracle command object
        ' Associate sql string (sqlstr) to command text
        ' Associate command type text as command type
        ' Associate oracle connection with commmand type connection
        ' Dimension oracle data reader
        ' Start 'try' to read data into array
        ' Use variable table column to read each value in the passed table column to the array
        ' Add count 1 to each value put in the array
        ' once array is populated use combobox parameter to additems to the combo box 
        ' Return the array
        ' Close the connection
        ' Dispose of the connection object
        Public Function populateComboDepts(ByVal cmbBox As ComboBox, _
                                            ByVal sqlStr As String, _
                                            ByVal tableCol As String, _
                                            ByVal connStr As String) As String()
    
            Dim array(0) As String
            Dim cnt As Integer = 0
            Dim conn As New OracleConnection
            conn.ConnectionString = connStr
            Try
                conn.Open()
            Catch ex As Exception
                MessageBox.Show("Error: " & ex.Message)
                MsgBox("Failed connection to Oracle" & ex.Message)
                'Return array
            End Try
            Dim cmd As New OracleCommand
            With cmd
                .CommandText = sqlStr
                .CommandType = CommandType.Text
                .Connection = conn
            End With
            Dim dr As OracleDataReader
            dr = cmd.ExecuteReader
            Try
                While dr.Read
                    ReDim Preserve array(cnt)
                    array(cnt) = dr.Item(tableCol)
                    cnt = cnt + 1
                End While
                'cmbBox.Items.Clear()
                cmbBox.Items.AddRange(array)
                'Return array
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Error")
                'Dim a(0) As String
                'a(0) = 0
                'Return a
            Finally
                conn.Close()
                conn.Dispose()
            End Try
            Return array
        End Function
    
        Public Sub connectToOra(ByVal queryStr1 As String)
            Try
                Dim xe As String = "Data Source=XE;User Id=hr;Password=hr;"
                Dim conn As New OracleConnection(xe) ' Associate connection string with connection object
                conn.Open()
                Dim sql1 As String = queryStr1
                'Dim sql2 As String = queryStr2
                Dim cmd As New OracleCommand(sql1, conn)
                cmd.CommandType = CommandType.Text
                Dim dr As OracleDataReader = cmd.ExecuteReader
                dr.Read()
                populateComboDepts(Me.cmbDepartments, sql1, "department_name", xe)
                'populateComboDeptID(cmbDeptID, sql2, "department_id", xe)
                conn.Dispose()
            Catch ex As Exception
                MessageBox.Show("Error: " & ex.Message)
            Finally
            End Try
        End Sub
    End Class
    Employees Class:

    Code:
    Public Class employees
        Private mEmployees As New Collection
    
        Public Function count() As Long
            count = mEmployees.Count
        End Function
    
    
        Public Sub remove(ByVal index As VariantType)
            mEmployees.Remove(index)
        End Sub
    
        Public Function item(ByVal index As VariantType) As employee
            item = mEmployees.Item(index)
        End Function
    
        Public Function newenum()
            newenum = mEmployees.GetEnumerator
        End Function
    
        Public Sub getEmployeeDetails()
            Dim usr1 As UserControl1
            usr1 = New UserControl1
            Dim ds As New DataSet
            Dim xe As String = "Data Source = XE; User id=hr;Password=hr;"
            Dim conn As New OracleConnection(xe)
            conn.Open()
            Dim myCmd As New OracleCommand
            myCmd.Connection = conn
            myCmd.CommandText = "curspkg_emp.emp_details_cursor1"
            myCmd.CommandType = CommandType.StoredProcedure
            myCmd.Parameters.Add(New OracleParameter("n_dept", OracleDbType.Varchar2)).Value = usr1.cmbDepartments.SelectedItem 
            << Here's where it is not picking up the selected item
            myCmd.Parameters.Add(New OracleParameter("io_cursor", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
    
            Dim dr As OracleDataReader = myCmd.ExecuteReader
            Dim emp As employee
            emp = New employee
            While dr.Read
                With emp
                    .EmployeeID = dr.Item("Employee_ID")
                    .FirstName = dr.Item("First_Name")
                    .LastName = dr.Item("Last_Name")
                    .Email = dr.Item("Email")
                    .PhoneNumber = dr.Item("Phone_Number")
                    .HireDate = dr.Item("Hire_Date")
                    .JobID = dr.Item("Job_ID")
                    .Salary = dr.Item("Salary").ToString
                    If IsDBNull(dr.Item("Commission_PCT")) Then
                        .CommissionPCT = 0
                    Else
                        .CommissionPCT = dr.Item("Commission_PCT")
                    End If
                    If IsDBNull(dr.Item("Manager_ID")) Then
                        .ManagerID = 0
                    Else
                        .ManagerID = dr.Item("Manager_ID")
                    End If
                    .DepartmentID = dr.Item("Department_ID")
                End With
                Dim lst As New ListViewItem
                Form1.ListView1.Items.Add(lst)
                lst.Text = dr.Item("Employee_ID")
                With lst.SubItems
                    .Add(dr.Item("First_Name"))
                    .Add(dr.Item("Last_Name"))
                    .Add(dr.Item("Email"))
                    .Add(dr.Item("Phone_Number"))
                    .Add(dr.Item("Hire_Date"))
                    .Add(dr.Item("Job_ID"))
                    .Add(dr.Item("Salary").ToString)
                    If IsDBNull(dr.Item("Commission_PCT")) Then
                        .Add(0)
                    Else
                        .Add(dr.Item("Commission_PCT"))
                    End If
                    If IsDBNull(dr.Item("Manager_ID")) Then
                        .Add(0)
                    Else
                        .Add(dr.Item("Manager_ID"))
                    End If
                    .Add(dr.Item("Department_ID"))
                    mEmployees.Add(emp)
                End With
                'Print("Hello")
                lst = Nothing
            End While
        End Sub
    End Class
    There is a form1 class but so little in it that's it's pointless posting. Now I think someone mentioned that if the selected item is nothing then it means it is not selected but when I had all the controls on the form it worked fine, all I have done is move the code to a user control.

    I think it's something to do with an incorrect instance setting or something but not exactly sure. I also notice that if I press F8 and go right through the code it loops through this bit twice In user control and tries to pick up a collection in employees class which isn't yet available. Is that right that it tries to pick up a collection, even when not there?:

    Code:
     Dim emp As New employees


    I still get a bit mixed up with these instances, does new mean a clean instance with no data or a newly created instance of an existing object or both, that is what gets me sometimes. Sometimes an instance is not declared as new, sometimes it is.

    Any ideas?

    G

  10. #10
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: UserControl Question

    Dim usr1 As UserControl1 'You have declared a variable that will hold a reference to an object, currently it does not point to anything
    usr1 = New UserControl1 'You have created a brand new usercontrol, assuming you have one on your form, this is then a second copy
    As you declared this inside a method you will loose reference to it when the method is complete.

    So when you call usr1.xxxx you are using the New copy which you can not see as you have never shown it to the user, and as such will have no values selected.

    The way to get around this (the quickest way anyway) is to pass the usercontrol that calls this method as a paramter so:

    Code:
    emp.getEmployeeDetails(Me) 
    ....
    Public Sub getEmployeeDetails(usr1 As UserControl1)
      'remove local declaration
      Dim ds As New DataSet
    ....

  11. #11
    PowerPoster
    Join Date
    Mar 2002
    Location
    UK
    Posts
    4,780

    Re: UserControl Question

    I think you are being confused by this:

    Form1.ListView1.Items.Clear()

    For some reason MS decided to bring back in default instance names for forms, to help those VB6 users who are converting up. When you call Form1.xxx if Form1 has never been created ie Dim Form1 As New Form1, then it will do it for you. You can access it from anywhere and things look much simpler to code, however you have just shot yourself in the foot in the design sense. You call Form1. while inside your UserControl1, which means that your usercontrol can not be placed on any form, only ever the default instance of Form1. The idea of a usercontrol is that you can re-use it, put it on Form2 put it on a different copy of Form1. Controls have the ability to raise events to tell their parents that an action is required.

    In your case you could do this

    Code:
    'At top of usercontrol
    Public Event SetupSelection()
    
    'Inside your sub instead of
       'Form1.ListView1.Items.Clear()
       'Form1.SetListViewColumns()
    RaiseEvent SetupSelection
    
    'Inside your form you can handle the UserControl1_SetupSelection event and add
    ListView1.Items.Clear()
    SetListViewColumns()
    This way the form and usercontrol do not interact with their local objects via anything other than their public interface. If the Form1 changes the ListView1 to a new name or you swap to a swanky new SuperListView1 then the usercontrol does not break.

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    Apr 2007
    Posts
    197

    Re: UserControl Question

    Hi

    I now have it working ok after doing what you said. This helps me understand the use of instances and user controls as well, which I am still trying to learn.

    Thanks for all the replies

    G

    Quote Originally Posted by Grimfort View Post
    Dim usr1 As UserControl1 'You have declared a variable that will hold a reference to an object, currently it does not point to anything
    usr1 = New UserControl1 'You have created a brand new usercontrol, assuming you have one on your form, this is then a second copy
    As you declared this inside a method you will loose reference to it when the method is complete.

    So when you call usr1.xxxx you are using the New copy which you can not see as you have never shown it to the user, and as such will have no values selected.

    The way to get around this (the quickest way anyway) is to pass the usercontrol that calls this method as a paramter so:

    Code:
    emp.getEmployeeDetails(Me) 
    ....
    Public Sub getEmployeeDetails(usr1 As UserControl1)
      'remove local declaration
      Dim ds As New DataSet
    ....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width