locked
Cascading combo box index change event not firing RRS feed

  • Question

  • Hallo,

    I am using following code given by Mr. Peter Fleischer. When i select an item from the 1st combo box , 2nd and 3rd combo box item changes but none of the event (eg. indexchanged, text changed or valuechanged, etc) for the combo box 2 and 3 are firing. Why?

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Controls.AddRange(New Control() {cb3, cb2, cb1})
            Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
            cb1.DisplayMember = "Master"
            cb1.DataSource = bs1
            Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
            cb2.DisplayMember = "Child"
            cb2.DataSource = bs2
            Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
            cb3.DisplayMember = "GrandChild"
            cb3.DataSource = bs3
        End Sub
    
        Private Function GetDataSet() As DataSet
            Dim ds As New DataSet
            With ds
                With .Tables.Add("Tab1")
                    With .Columns
                        .Add("ID", GetType(Integer))
                        .Add("Master", GetType(String))
                    End With
                End With
                With .Tables.Add("Tab2")
                    With .Columns
                        .Add("ID", GetType(Integer))
                        .Add("FKMaster", GetType(Integer))
                        .Add("Child", GetType(String))
                    End With
                End With
                With .Tables.Add("Tab3")
                    With .Columns
                        .Add("ID", GetType(Integer))
                        .Add("FKChild", GetType(Integer))
                        .Add("GrandChild", GetType(String))
                    End With
                End With
                For i = 0 To 9
                    .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
                    For k = i * 10 To i * 10 + 9
                        .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
                        For l = k * 10 To k * 10 + 9
                            .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
                        Next
                    Next
                Next
                .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
                .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
            End With
            Return ds
        End Function
    
        Private Sub cb2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cb2.SelectedIndexChanged
            MessageBox.Show("selection changed")
        End Sub
    End Class
    

    I don't see the message "selection changed" when i change something in combo box 1.

    Tuesday, April 14, 2020 2:59 PM

Answers

  • Hi,
    I didn't unterstand your problem. If you use event SelectedIndexChanged and SelectedIndex do not changed the event don't raise. If you want to get an event when the value changed then use SelectedValueChanged event like in this demo:

    Public Class Form1
    
      Private WithEvents cb1 As New ComboBox With {.Top = 50, .Width = 150, .DisplayMember = "Master"}
      Private WithEvents cb2 As New ComboBox With {.Top = 100, .Width = 150, .DisplayMember = "Child"}
      Private WithEvents cb3 As New ComboBox With {.Top = 150, .Width = 150, .DisplayMember = "GrandChild"}
      Private lbl1 As New Label With {.Top = 50, .Left = 250, .Width = 150}
      Private lbl2 As New Label With {.Top = 100, .Left = 250, .Width = 150}
      Private lbl3 As New Label With {.Top = 150, .Left = 250, .Width = 150}
    
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {lbl3, lbl2, lbl1, cb3, cb2, cb1})
        Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
        cb1.DataSource = bs1
        Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
        cb2.DataSource = bs2
        Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
        cb3.DataSource = bs3
      End Sub
    
      Private Function GetDataSet() As DataSet
        Dim ds As New DataSet
        With ds
          With .Tables.Add("Tab1")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("Master", GetType(String))
            End With
          End With
          With .Tables.Add("Tab2")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKMaster", GetType(Integer))
              .Add("Child", GetType(String))
            End With
          End With
          With .Tables.Add("Tab3")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKChild", GetType(Integer))
              .Add("GrandChild", GetType(String))
            End With
          End With
          For i = 0 To 9
            .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
            For k = i * 10 To i * 10 + 9
              .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
              For l = k * 10 To k * 10 + 9
                .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
              Next
            Next
          Next
          .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
          .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
        End With
        Return ds
      End Function
    
    
      Private Sub cb1_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb1.SelectedValueChanged
        lbl1.Text = cb1.Text
      End Sub
    
      Private Sub cb2_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb2.SelectedValueChanged
        lbl2.Text = cb2.Text
      End Sub
    
      Private Sub cb3_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb3.SelectedValueChanged
        lbl3.Text = cb3.Text
      End Sub
    
    End Class


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    • Marked as answer by Shan1986 Tuesday, April 14, 2020 5:49 PM
    Tuesday, April 14, 2020 5:31 PM

All replies

  • Because it is a sample. This is not a code service. Peter gave a sample. Only CB2 fires. The other ones you have to do yourself. 

    Success
    Cor

    Tuesday, April 14, 2020 3:25 PM
  • Because it is a sample. This is not a code service. Peter gave a sample. Only CB2 fires. The other ones you have to do yourself. 

    Success
    Cor

    sorry ..even cb2 does not fire..
    Tuesday, April 14, 2020 3:40 PM
  • Hello,

    Here is a C# example I wrote with the VB.NET code below, no relationships on this one. It shows main ComboBox and secondary ComboBox, third works from following code logic in the first two.

    Namespace ComboBoxToComboBoxSqlServer
    	Partial Public Class Form1
    		Inherits Form
    
    		Private ReadOnly _productBindingSource As New BindingSource()
    		Public Sub New()
    			InitializeComponent()
    			AddHandler CategoryComboBox.SelectedIndexChanged, AddressOf CategoryComboBox_SelectedIndexChanged
    		End Sub
    
    		Private Sub CategoryComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
    			If CategoryComboBox.SelectedItem Is Nothing Then
    				Return
    			End If
    
    			Dim categoryIdentifier = CType(CategoryComboBox.SelectedItem, DataRowView).Row.Field(Of Integer)("CategoryId")
    
    			_productBindingSource.Filter = $"CategoryId = {categoryIdentifier}"
    		End Sub
    
    		Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
    			Dim ops = New DataOperations()
    			CategoryComboBox.DisplayMember = "CategoryName"
    
    			CategoryComboBox.DataSource = ops.CategoryDataTable()
    
    			ProductComboBox.DisplayMember = "ProductName"
    
    			_productBindingSource.DataSource = ops.ProductDataTable()
    			ProductComboBox.DataSource = _productBindingSource
    		End Sub
    	End Class
    End Namespace


    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, April 14, 2020 3:47 PM
  • Because it is a sample. This is not a code service. Peter gave a sample. Only CB2 fires. The other ones you have to do yourself. 


    Success
    Cor

    sorry ..even cb2 does not fire..

    Really?


    Success
    Cor

    Tuesday, April 14, 2020 4:10 PM
  • Hi,
    try my demo with event receiver for SelectedIndexChanged. It works very fine.

    Public Class Form1
    
      Private WithEvents cb1 As New ComboBox With {.Top = 50, .Width = 150, .DisplayMember = "Master"}
      Private WithEvents cb2 As New ComboBox With {.Top = 100, .Width = 150, .DisplayMember = "Child"}
      Private WithEvents cb3 As New ComboBox With {.Top = 150, .Width = 150, .DisplayMember = "GrandChild"}
    
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {cb3, cb2, cb1})
        Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
        cb1.DataSource = bs1
        Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
        cb2.DataSource = bs2
        Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
        cb3.DataSource = bs3
      End Sub
    
      Private Function GetDataSet() As DataSet
        Dim ds As New DataSet
        With ds
          With .Tables.Add("Tab1")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("Master", GetType(String))
            End With
          End With
          With .Tables.Add("Tab2")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKMaster", GetType(Integer))
              .Add("Child", GetType(String))
            End With
          End With
          With .Tables.Add("Tab3")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKChild", GetType(Integer))
              .Add("GrandChild", GetType(String))
            End With
          End With
          For i = 0 To 9
            .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
            For k = i * 10 To i * 10 + 9
              .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
              For l = k * 10 To k * 10 + 9
                .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
              Next
            Next
          Next
          .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
          .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
        End With
        Return ds
      End Function
    
    
      Private Sub cb1_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb1.SelectedIndexChanged, cb2.SelectedIndexChanged, cb3.SelectedIndexChanged
        Debug.WriteLine(CType(sender, ComboBox).DisplayMember)
      End Sub
    
    End Class


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks


    Tuesday, April 14, 2020 4:26 PM
  • Hi,
    try my demo with event receiver for SelectedIndexChanged. It works very fine.

    Public Class Form1
    
      Private WithEvents cb1 As New ComboBox With {.Top = 50, .Width = 150, .DisplayMember = "Master"}
      Private WithEvents cb2 As New ComboBox With {.Top = 100, .Width = 150, .DisplayMember = "Child"}
      Private WithEvents cb3 As New ComboBox With {.Top = 150, .Width = 150, .DisplayMember = "GrandChild"}
    
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {cb3, cb2, cb1})
        Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
        cb1.DataSource = bs1
        Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
        cb2.DataSource = bs2
        Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
        cb3.DataSource = bs3
      End Sub
    
      Private Function GetDataSet() As DataSet
        Dim ds As New DataSet
        With ds
          With .Tables.Add("Tab1")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("Master", GetType(String))
            End With
          End With
          With .Tables.Add("Tab2")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKMaster", GetType(Integer))
              .Add("Child", GetType(String))
            End With
          End With
          With .Tables.Add("Tab3")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKChild", GetType(Integer))
              .Add("GrandChild", GetType(String))
            End With
          End With
          For i = 0 To 9
            .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
            For k = i * 10 To i * 10 + 9
              .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
              For l = k * 10 To k * 10 + 9
                .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
              Next
            Next
          Next
          .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
          .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
        End With
        Return ds
      End Function
    
    
      Private Sub cb1_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb1.SelectedIndexChanged, cb2.SelectedIndexChanged, cb3.SelectedIndexChanged
        Debug.WriteLine(CType(sender, ComboBox).DisplayMember)
      End Sub
    
    End Class


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks


    hallo peter, Still it is not working as it should please see my recording .. 

    it shows child only once after i manually change in cb2..same for cb3. not every time i change the cb1.

    Tuesday, April 14, 2020 4:50 PM
  • Hi,
    I didn't unterstand your problem. If you use event SelectedIndexChanged and SelectedIndex do not changed the event don't raise. If you want to get an event when the value changed then use SelectedValueChanged event like in this demo:

    Public Class Form1
    
      Private WithEvents cb1 As New ComboBox With {.Top = 50, .Width = 150, .DisplayMember = "Master"}
      Private WithEvents cb2 As New ComboBox With {.Top = 100, .Width = 150, .DisplayMember = "Child"}
      Private WithEvents cb3 As New ComboBox With {.Top = 150, .Width = 150, .DisplayMember = "GrandChild"}
      Private lbl1 As New Label With {.Top = 50, .Left = 250, .Width = 150}
      Private lbl2 As New Label With {.Top = 100, .Left = 250, .Width = 150}
      Private lbl3 As New Label With {.Top = 150, .Left = 250, .Width = 150}
    
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {lbl3, lbl2, lbl1, cb3, cb2, cb1})
        Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
        cb1.DataSource = bs1
        Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
        cb2.DataSource = bs2
        Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
        cb3.DataSource = bs3
      End Sub
    
      Private Function GetDataSet() As DataSet
        Dim ds As New DataSet
        With ds
          With .Tables.Add("Tab1")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("Master", GetType(String))
            End With
          End With
          With .Tables.Add("Tab2")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKMaster", GetType(Integer))
              .Add("Child", GetType(String))
            End With
          End With
          With .Tables.Add("Tab3")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKChild", GetType(Integer))
              .Add("GrandChild", GetType(String))
            End With
          End With
          For i = 0 To 9
            .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
            For k = i * 10 To i * 10 + 9
              .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
              For l = k * 10 To k * 10 + 9
                .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
              Next
            Next
          Next
          .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
          .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
        End With
        Return ds
      End Function
    
    
      Private Sub cb1_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb1.SelectedValueChanged
        lbl1.Text = cb1.Text
      End Sub
    
      Private Sub cb2_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb2.SelectedValueChanged
        lbl2.Text = cb2.Text
      End Sub
    
      Private Sub cb3_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb3.SelectedValueChanged
        lbl3.Text = cb3.Text
      End Sub
    
    End Class


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    • Marked as answer by Shan1986 Tuesday, April 14, 2020 5:49 PM
    Tuesday, April 14, 2020 5:31 PM

  • hallo peter, Still it is not working as it should please see my recording .. 

    it shows child only once after i manually change in cb2..same for cb3. not every time i change the cb1.

    Hi

    So, what you are actually saying is 'I don't understand the code'. It is 'working as it should' here!

    Here is the same code, altered only to suit my poor eyesight and to display ALL the calls to the 'cb1_SelectedIndexChanged'

    This version puts a multiline rexrbox onto the Form and records all the calls. Please examine those results and see if indeed it IS working as it should?

    ' Blank Form1
    Option Strict Off
    Option Explicit Off
    Public Class Form1
      Private WithEvents cb1 As New ComboBox With {.Left = 20, .Top = 30, .Width = 200, .DisplayMember = "Master", .Font = New Font("Arial", 14)}
      Private WithEvents cb2 As New ComboBox With {.Left = 20, .Top = 80, .Width = 200, .DisplayMember = "Child", .Font = New Font("Arial", 14)}
      Private WithEvents cb3 As New ComboBox With {.Left = 20, .Top = 130, .Width = 200, .DisplayMember = "GrandChild", .Font = New Font("Arial", 14)}
      Dim TB As New TextBox With {.Left = 20, .Width = 600, .Top = 190, .Height = 1000, .Font = New Font("Arial", 24), .Multiline = True, .AutoSize = True, .Text = "Display Member"}
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Controls.AddRange(New Control() {cb3, cb2, cb1, TB})
        Dim bs1 As New BindingSource With {.DataSource = GetDataSet(), .DataMember = "Tab1"}
        cb1.DataSource = bs1
        Dim bs2 As New BindingSource With {.DataSource = bs1, .DataMember = "Rel1"}
        cb2.DataSource = bs2
        Dim bs3 As New BindingSource With {.DataSource = bs2, .DataMember = "Rel2"}
        cb3.DataSource = bs3
      End Sub
      Private Function GetDataSet() As DataSet
        Dim ds As New DataSet
        With ds
          With .Tables.Add("Tab1")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("Master", GetType(String))
            End With
          End With
          With .Tables.Add("Tab2")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKMaster", GetType(Integer))
              .Add("Child", GetType(String))
            End With
          End With
          With .Tables.Add("Tab3")
            With .Columns
              .Add("ID", GetType(Integer))
              .Add("FKChild", GetType(Integer))
              .Add("GrandChild", GetType(String))
            End With
          End With
          For i = 0 To 9
            .Tables("Tab1").Rows.Add(i, $"Master {i + 1}")
            For k = i * 10 To i * 10 + 9
              .Tables("Tab2").Rows.Add(k, i, $"Child {i + 1}-{k + 1}")
              For l = k * 10 To k * 10 + 9
                .Tables("Tab3").Rows.Add(l, k, $"Grandchild {i + 1}-{k + 1}-{l + 1}")
              Next
            Next
          Next
          .Relations.Add("Rel1", .Tables("Tab1").Columns("ID"), .Tables("Tab2").Columns("FKMaster"))
          .Relations.Add("Rel2", .Tables("Tab2").Columns("ID"), .Tables("Tab3").Columns("FKChild"))
        End With
        Return ds
      End Function
      Private Sub cb1_SelectedIndexChanged(sender As Object, e As EventArgs) _
        Handles cb1.SelectedIndexChanged, cb2.SelectedIndexChanged, cb3.SelectedIndexChanged
        TB.AppendText(CType(sender, ComboBox).DisplayMember & vbCrLf)
      End Sub
    End Class
    


    Regards Les, Livingston, Scotland

    Tuesday, April 14, 2020 5:47 PM