none
List of ComboBox elements RRS feed

  • Question

  • I need to recreate a MS-Access "sub-form" in VisualBasic, something like this:

    As you can see, there are three "nested" ComboBoxes in ListBox1.

    I experimented with the following code to no avail (nothing is showing in the interface at run time) :

            Dim ComboBox1 As New ComboBox
            ComboBox1.Items.Add("Sugar")
            ComboBox1.Items.Add("Honey")
            ListBox1.Items.Add(ComboBox1)

    Once I figure out "how" to add ComboBoxes (provided it is possible) then I will need to manage the List, by adding new ComboBoxes or deleting ComboBoxes.

    Thank you so much for your help in advance.

    Tuesday, March 17, 2020 9:05 PM

Answers

  • I finally decided to use a ListView control, with an Add and a Delete button.
    The MS-Access drop-down menu style of interface did not "port" well to VisualBasic.

    A Panel and a custom DataGriView would have done the job but I'm satisfied with the ListView interface I manage to put together. Given my relative inexperience in programming and the time I have to put this part of the application together, I deemed the ListView approach was the most satisfactory.

    Thank you so much everyone for your patient and kind help. This is the interface:

    First, I have a ComboBox in which I list all the existing clients.

    Then, the user simply locate a given client and hit the Add button, to add the client to the ListView.
    To delete a client from the ListView, simply click the client name and hit the Del button.


    • Marked as answer by roger.breton Sunday, March 29, 2020 9:56 PM
    • Edited by roger.breton Sunday, March 29, 2020 10:04 PM Forgot the screen capture
    Sunday, March 29, 2020 9:55 PM

All replies

  • Hi

    Here is 3 ways to add Comboboxes and data,

    ' Form1 with CB1, CB2 and CB3
    Option Strict On
    Option Explicit On
    Public Class Form1
      Dim CB1, CB2, CB3 As New ComboBox
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
        With CB1
          .Location = New Point(20, 20)
          For i As Integer = 789 To 801
            .Items.Add(i.ToString)
          Next
        End With
    
        With CB2
          .Location = New Point(20, 50)
          .Items.AddRange({"Mary", "Brian", "Archibald"})
        End With
    
        Dim lst As New List(Of String)
        lst.AddRange({"A", "B", "C", "D", "E", "F", "G"})
        With CB3
          .Location = New Point(20, 80)
          CB3.DataSource = lst
        End With
        Controls.AddRange({CB1, CB2, CB3})
      End Sub
    End Class


    Regards Les, Livingston, Scotland

    Tuesday, March 17, 2020 9:17 PM
  • Hi Les,

    I copied and pasted your code into a new project and, when I executed it, I got the following:

    I need for the ComboBoxes to show *inside* a ListBox. Unless I miss something, the three ComboBoxes are "independent" of each other and display at fixed locations on the form :(

    Tuesday, March 17, 2020 9:25 PM
  • Hi

    A ListBox can't contain ComboBoxes as items, and yes, they will always be "independent" of each other even when in another container.

    You could have a Panel containing them like below.

    ' Blank Form1
    Option Strict On
    Option Explicit On
    Public Class Form1
      Dim pan As New Panel
      Dim CB1, CB2, CB3 As New ComboBox
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        With pan
          .Location = New Point(20, 20)
          .Size = New Size(135, 96)
          .BackColor = Color.Khaki
          .BorderStyle = BorderStyle.FixedSingle
        End With
        With CB1
          .Location = New Point(5, 5)
          For i As Integer = 789 To 801
            .Items.Add(i.ToString)
          Next
        End With
    
        With CB2
          .Location = New Point(5, 35)
          .Items.AddRange({"Mary", "Brian", "Archibald"})
        End With
    
        Dim lst As New List(Of String)
        lst.AddRange({"A", "B", "C", "D", "E", "F", "G"})
        With CB3
          .Location = New Point(5, 65)
          CB3.DataSource = lst
        End With
        pan.Controls.AddRange({CB1, CB2, CB3})
        Controls.Add(pan)
      End Sub
    End Class


    Regards Les, Livingston, Scotland



    • Edited by leshay Tuesday, March 17, 2020 9:48 PM
    Tuesday, March 17, 2020 9:46 PM
  • Lester,

    I gave that code a try and got the following:

    Not what I'm looking for. I realize that A ListBox can't contain ComboBoxes as items

    Sigh :(

    I was thinking, perhaps, a ListView or a DataGridView, with a check box? I have a list of client that comes from a database that I could display in a List form, and allow the user to select only those clients that are "relevant" by checking a checkbox opposite each client? I have some code that looks like this :

    It is not ideal but it may work. Worth giving a try... I'll look at that code, in case I can re-use it, in a modified form. Of course, the first column would be the client name and the second column would be the check box.


    Tuesday, March 17, 2020 9:59 PM
  • Les,

    I found and modified the code but it's not going to do the job. I'll experiment with DataGridView.

    Tuesday, March 17, 2020 10:55 PM
  • Hi

    Yes, a DataGridview can have ComboBox columns.


    Regards Les, Livingston, Scotland

    Tuesday, March 17, 2020 11:10 PM
  • If you want to work with a ListView I have a code sample that may help. In the screenshot below a ListView is used with ListView groups but does not need to use groups. Data is loaded in this case from SQL-Server while changing the data provider will work just fine with other databases such as Oracle, Microsoft Access.

    The "Select products" code collects the checked items, they can span groups in this case so the code works without groups.

    The "Hover Selection" is a optional behavior to track the row under the mouse. The labels below are informational.

    Some items "In stock" are 0 have a red foreground color to show how to do simply font styling.

    Full source with database scripts

    https://github.com/karenpayneoregon/ListViewWindowsFormsVisualBasic

    Each row has primary keys stored as per below, in this case rows are fetched using SQL with joins.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, March 17, 2020 11:12 PM
    Moderator
  • Hi

    Here is some code that will add ComboBoxes to a DataGridViewColumn (I added a single TextBox column to DataGridView1 in theDesigner). This example adds as many ComboBoxes as there are rows, each ComboBox has different values (randoms).

    ' Blank with DataGridView1
    ' with a Column named Column1
    Option Strict On
    Option Explicit On
    Public Class Form1
      Dim rand As New Random
    
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
        With DataGridView1
          For i As Integer = 0 To 8
            .Rows.Add()
          Next
        End With
    
        For r As Integer = 0 To DataGridView1.Rows.Count - 1
          Dim cbc As New DataGridViewComboBoxCell
          cbc.Items.Add(rand.Next(9, 99).ToString)
          cbc.Items.Add(rand.Next(9, 99).ToString)
          cbc.Items.Add(rand.Next(9, 99).ToString)
          DataGridView1.Item("Column1", r) = cbc
        Next
    
      End Sub
    End Class


    Regards Les, Livingston, Scotland

    Tuesday, March 17, 2020 11:45 PM
  • Thank you, Karen. You've given me "Food for thoughts". I think I owe you guys a better idea of what it is, exactly, I am up against. This is the current Microsoft Access interface:

    As you can see, it is a One to Many relationship, where the code QA65745A could be used by a number of clients, listed in a sub-form to the right. What Access does very well is to dynamically add comboboxes to the subform. Right now, there are four clients using QA65745A but there could be more. So as soon as the last combobox fills, Access immediately appends a new one at the bottom. All the technician has to do is to click the mouse on the new combobox and the whole client list displays, sorted alphabetically, and all he has to do is to start typing the first few letters ('AutoComplete feature?) of the client name for the entry to be selected in the combobox. It could not be simpler and faster. 

    So that's the interface I was considering building with the idea of "List of ComboBoxes" but that can't be done, as Lex explained. (Unless I go to great programming length and I'm not a seasoned programmer). So, I was considering, perhaps, a ListView with a checkbox or a DataGridView with a ComboBox Column. Lucky for me, I only have about 125 clients to contend with.

    Wednesday, March 18, 2020 12:05 AM
  • Les, 

    I tried your code (had to add the Columns):

    And I think it is going in the right direction. I changed your random entries for some known company names, as you can see from the screen capture. I only entered 6 company names but it was enough to test the expected "ComboBox" behavior. 

    If I was to use this approach, I would first read the whole customer list into the DataGridViewComboBoxCellThen, I'd have to display check boxex for each row and allow the user to check or uncheck as the need be. 

    I think it's feasible. I'm going to let the idea percolate... Thank you so much for your help.

    I like Karen's suggestion too :-)

    Wednesday, March 18, 2020 12:24 AM
  • So that's the interface I was considering building with the idea of "List of ComboBoxes" but that can't be done, as Lex explained. (Unless I go to great programming length and I'm not a seasoned programmer). So, I was considering, perhaps, a ListView with a checkbox or a DataGridView with a ComboBox Column. Lucky for me, I only have about 125 clients to contend with.

    Can't you just use a Panel, with AutoScroll = True ?

    Wednesday, March 18, 2020 1:08 AM
  • Dear Castorix31,

    I must say your animated demo is impressive. One problem I see is that (please correct me if I am wrong?) I need to lay out a Panel with as many ComboBoxes as I have clients! Here, in the above animation, there are not too many ComboBoxes, but with 125 Client? Even if I use the Panel Autoscroll = True, I still need to copy and paste 125+ ComboBoxes in my WinForm?

    Wednesday, March 18, 2020 1:14 AM
  • Les, 

    I tried your code (had to add the Columns):

    And I think it is going in the right direction. I changed your random entries for some known company names, as you can see from the screen capture. I only entered 6 company names but it was enough to test the expected "ComboBox" behavior. 

    If I was to use this approach, I would first read the whole customer list into the DataGridViewComboBoxCellThen, I'd have to display check boxex for each row and allow the user to check or uncheck as the need be. 

    I think it's feasible. I'm going to let the idea percolate... Thank you so much for your help.

    I like Karen's suggestion too :-)

    Hi

    OK, I believe you might need all of the CB in the group to have the same drop down items, updated as new users are added  (and presumably removed) - is that correct? I had thought you wanted discrete control over each CB in the list.

    It does help when you explain more fully.


    Regards Les, Livingston, Scotland

    Wednesday, March 18, 2020 1:15 AM
  • Dear Lester,

    I am sorry if I did not make myself clear at the onset. Blame it on inexperience.
    I do my best to convey my meanings. You are right, I need ALL the ComboBoxes to have the same drop down items, exactly as in the MS-Access database implementation. (Removed? No, not in this interface) Sorry, no, discrete control over each ComboBox is not what I am after. I wish I was the KING of "interface design"...


    Wednesday, March 18, 2020 1:20 AM
  • I need to lay out a Panel with as many ComboBoxes as I have clients! Here, in the above animation, there are not too many ComboBoxes, but with 125 Client? Even if I use the Panel Autoscroll = True, I still need to copy and paste 125+ ComboBoxes in my WinForm?

    They are not created in the Designer

    For the test, I just created 10 Combo Boxes dynamically in a simple loop, but you can create 125 or any number

    Wednesday, March 18, 2020 1:23 AM
  • Thank you, Karen. You've given me "Food for thoughts". I think I owe you guys a better idea of what it is, exactly, I am up against. This is the current Microsoft Access interface:

    As you can see, it is a One to Many relationship, where the code QA65745A could be used by a number of clients, listed in a sub-form to the right. What Access does very well is to dynamically add comboboxes to the subform. Right now, there are four clients using QA65745A but there could be more. So as soon as the last combobox fills, Access immediately appends a new one at the bottom. All the technician has to do is to click the mouse on the new combobox and the whole client list displays, sorted alphabetically, and all he has to do is to start typing the first few letters ('AutoComplete feature?) of the client name for the entry to be selected in the combobox. It could not be simpler and faster. 

    So that's the interface I was considering building with the idea of "List of ComboBoxes" but that can't be done, as Lex explained. (Unless I go to great programming length and I'm not a seasoned programmer). So, I was considering, perhaps, a ListView with a checkbox or a DataGridView with a ComboBox Column. Lucky for me, I only have about 125 clients to contend with.

    The following can be done with a DataGridView with ComboBox columns and a BindingNavigator where the setup is easy but dependent on full logic of what you need to do with this and your expertise with VB.NET might be time consuming yet not out of reach.

     

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Wednesday, March 18, 2020 1:41 AM
    Moderator
  • I completely missed the point that the ComboBoxes can be created dynamically!
    Thank you so much!! 

    Could you please share the code you used?

    Wednesday, March 18, 2020 1:15 PM
  • I completely missed the point that the ComboBoxes can be created dynamically!
    Thank you so much!! 

    Could you please share the code you used?

    It's a quick test with random data, locations, sizes; just for the idea (50 created in this test) =>

      Friend WithEvents Panel1 As Panel
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Panel1 = New Panel()
            Panel1.AutoScroll = True
            Panel1.Location = New System.Drawing.Point(10, 10)
            Panel1.Size = New System.Drawing.Size(160, 200)
            Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
            Controls.Add(Panel1)
    
            Dim lst As New List(Of String)
            lst.AddRange({"IBM", "Oracle", "Sun Microsystems", "CitiGroup", "Microsoft Corporation", "Amazon", "TimeWarner", "Apple"})
    
            Dim nX As Integer = 10
            Dim nY As Integer = 10
            For i As Integer = 0 To 50
                Dim myComboBox = New ComboBox
                With myComboBox
                    .BindingContext = New BindingContext()
                    .Location = New System.Drawing.Point(nX, nY)
                    .DataSource = lst
                    .SelectedIndex = i Mod lst.Count
                End With
                Panel1.Controls.Add(myComboBox)
                nY += 30
            Next
            CenterToScreen()
        End Sub

    Wednesday, March 18, 2020 2:35 PM
  • Thank you so much, Castorix! I will give your code a try...

    Meanwhile, I experimented with a DataGridViewComboboxColumn. I am posting the code in case someone else wants to experiment with it (it's not "pretty code" but it allows me to experiment with the approach):

    Dim DataSet1 As New DataSet ' Table Count = 0
    
            Dim Conn As New SqlConnection("Server=XPS8930\SQLEXPRESS;Database=CIM;Trusted_Connection=True")
            Dim Command As New SqlCommand("SELECT [NomClient] FROM [dbo].[Client] ORDER BY [NomClient] ASC", Conn)
    
            'Constructor
            Dim sqlAdapter As New SqlDataAdapter(Command)
    
            sqlAdapter.Fill(DataSet1, “Client”) '154 Rows
    
            Dim DataTable1 As DataTable
            DataTable1 = New DataTable(“Data”)
    
            Dim myDataColumn As DataColumn
            Dim myDataRow As DataRow
    
            myDataColumn = New DataColumn
            myDataColumn.DataType = System.Type.GetType(“System.String”)
            myDataColumn.ColumnName = “Column1”
            DataTable1.Columns.Add(myDataColumn)
    
            'myDataColumn = New DataColumn
            'myDataColumn.DataType = System.Type.GetType(“System.Single”)
            'myDataColumn.ColumnName = “Column2”
            'DataTable1.Columns.Add(myDataColumn)
    
            DataSet1.Tables.Add(DataTable1)
    
            Dim i As Integer
            For i = 1 To 10
                myDataRow = DataTable1.NewRow
                DataTable1.Rows.Add(myDataRow)
            Next
    
            Dim comboBoxColumn As New DataGridViewComboBoxColumn
            DataGridView2.DefaultCellStyle.Font = New Font("Tahoma", 14)
            DataGridView2.AutoGenerateColumns = False
            DataGridView2.DataSource = DataSet1
            DataGridView2.DataMember = “Data”   ' Child list for field Data cannot be created
    
            comboBoxColumn.Name = “Nom Client1”
            comboBoxColumn.DataPropertyName = “Column1”
            comboBoxColumn.Width = “300”
            comboBoxColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            comboBoxColumn.DefaultCellStyle.ForeColor = Color.Black
            comboBoxColumn.DefaultCellStyle.BackColor = Color.LightGray
            comboBoxColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing
            comboBoxColumn.ReadOnly = False
    
            DataGridView2.Columns.Insert(0, comboBoxColumn)
    
            comboBoxColumn.DataSource = DataSet1.Tables(“Client”)   ' DataSource prend une Table en argument
            comboBoxColumn.DisplayMember = “NomClient”
    It is a "step" in the right direction but I am not out of the woods yet. This approach or Castorix approach will do the job BUT there is a bigger problem, and that is, when I read the database and find out the exact Clients that need to be displayed, I have to think of how I am going to deal with the "DataSource" since will always be a subset of the whole 154 clients. I guess I have to go flag only the Client that needs to be display (could be as low as 1 or as high as 10 but I have not seen more than 10), initialize the ComboBox "cells" with those but then, I have to make available the whole 154 list of Clients in case the user wants to assign a new Client. That's probably not very clear -- I'm sorry. MS Access was doing all of this on its own...



    Thursday, March 19, 2020 3:23 AM
  • I finally decided to use a ListView control, with an Add and a Delete button.
    The MS-Access drop-down menu style of interface did not "port" well to VisualBasic.

    A Panel and a custom DataGriView would have done the job but I'm satisfied with the ListView interface I manage to put together. Given my relative inexperience in programming and the time I have to put this part of the application together, I deemed the ListView approach was the most satisfactory.

    Thank you so much everyone for your patient and kind help. This is the interface:

    First, I have a ComboBox in which I list all the existing clients.

    Then, the user simply locate a given client and hit the Add button, to add the client to the ListView.
    To delete a client from the ListView, simply click the client name and hit the Del button.


    • Marked as answer by roger.breton Sunday, March 29, 2020 9:56 PM
    • Edited by roger.breton Sunday, March 29, 2020 10:04 PM Forgot the screen capture
    Sunday, March 29, 2020 9:55 PM