Belajar Programming | Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat, adalah salah satu teknik yang sering ditanyakan di forum-forum pemrograman. Dengan teknik ini, kita membuat seolah-olah beberapa dropdown list atau combobox saling berhubungan, misalkan combobox nama-nama kota akan terisi otomatis sesuai dengan pilihan negara di combobox lainnya. Atau combobox list pegawai akan berubah sesuai dengan departemen yang dipilih. Teknik ini sebenarnya sangatlah sederhana, namun memerlukan pemahaman yang cukup komprehensif mengenai mengenai beberapa hal, seperti cara mengambil data dari database, cara mengisi data ke combobox atau dropdown list, dan cara mengambil pilihan pengguna sebagai referensi untuk mengisi combobox lainnya.

Belajar Programming | Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat, adalah salah satu teknik yang sering ditanyakan di forum-forum pemrograman. Dengan teknik ini, kita membuat seolah-olah beberapa dropdown list atau combobox saling berhubungan, misalkan combobox nama-nama kota akan terisi otomatis sesuai dengan pilihan negara di combobox lainnya. Atau combobox list pegawai akan berubah sesuai dengan departemen yang dipilih. Teknik ini sebenarnya sangatlah sederhana, namun memerlukan pemahaman yang cukup komprehensif mengenai mengenai beberapa hal, seperti

  • cara mengambil data dari database
  • cara mengisi data ke combobox atau dropdown list
  • cara mengambil pilihan pengguna sebagai referensi untuk mengisi combobox lainnya.

Berikut ini saya coba jabarkan implementasi Teknik Combo Box Bertingkat menggunakan query ADO.NET sederhana saja. Untuk studi kasus ini, kita akan coba menghubungkan 3 (tiga) buah combobox yang berisikan daftar benua – negara – kota. Combobox Negara akan terisi sesuai dengan Benua yang dipilih, dan Combobox Kota akan terisi sesuai dengan Negara yang dipilih. Sedangkan bahasa pemrograman yang dipakai adalah C# dan VB.net untuk memudahkan teman-teman memahaminya. 

Devide and Conquer

Dengan sedikit analisa sederhana terhadap kasus ini, kita coba pecah kasus ini menjadi beberapa kasus kecil untuk mempermudah kita menyelesaikannya, antara lain,

  • bagaimana desain yang pas untuk kasus seperti ini
  • bagaimana cara mengisi combobox benua
  • bagaimana cara mengisi combobox negara
  • bagaimana cara mengisi combobox kota
  • bagaimana cara menangkap perubahan pilihan benua
  • bagaimana cara menangkap perubahan pilihan negara

Teknik "memecah problem besar menjadi beberapa problem-problem kecil" adalah salah satu teknik untuk membangun algoritma, yaitu teknik devide and conquer. Dengan memecah problem besar menjadi sejumlah problem kecil, kelihatannya memang seolah problem yang dihadapi menjadi semakin banyak, namun… walaupun kelihatan banyak, sejumlah problem kecil ini justru jauh lebih mudah kita selesaikan sehingga problem besar utama kita otomatis ikut terpecahkan.

Mari Kita Mulai…!

Pertama-tama, desain database harus kita buat dengan hati-hati agar mudah dalam proses retrieval atau pengambilan datanya. Cara paling efektif adalah denga membuat 3 (tiga) buah table yang saling berelasi, yaitu table Continents, table Countries dengan foreign key yang berelasi ke table Continents. dan terakhir, table Cities dengan foreign key yang berelasi dengan table Countries. Seperti terlihat pada gambar di bawah ini.

[collapsed title=Desain Database seperti ini] Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat [/collapsed]

Sedangkan untuk desain Form, kita buat desain sederhana saja seperti  yang ada di gambar ini.

[collapsed title=Desain Form seperti ini] Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat [/collapsed]

Mengisi Combobox dari Database

Untuk mengisi Combo Box, algoritma-nya adalah seperti ini,

  • Siapkan koneksi database
  • Ambil data dari database 
  • Binding data ke combobox

Dengan mengetahui langkah-langkah dasar di atas, maka kita bisa dengan mudah menterjemahkannya ke bahasa pemrograman apapun. Untuk keperluan ini, kita membuat tiga buah fungsi FillComboContinents, FillComboCountries, dan FillComboCities, masing-masing untuk mengisi data benua, negara, dan kota. Dalam bahasa pemrograman VB.net seperti ini.

[collapsed title=Pengambilan Data Versi VB.net]

''' <summary>
''' Mengisi Combo Box pertama (continents)
''' </summary>
Private Sub FillComboContinents()
    ' siapkan variable koneksi database
    Dim cn As New SqlCeConnection(My.MySettings.Default.dbSampleConnectionString)
    Dim da As New SqlCeDataAdapter("SELECT * FROM Continents", cn)
    ' siapkan data table untuk menampung data dari database
    Dim dt As New DataTable()
    ' selalu gunakan try-catch block
    Try
        ' isi dataset
        da.Fill(dt)
        ' binding dataset ke combobox kedua
        comboBox1.ValueMember = "ID"
        comboBox1.DisplayMember = "Name"
        comboBox1.DataSource = dt
    Catch ex As Exception
        ' infokan ke user, jika ada error
        MessageBox.Show(ex.Message)
    End Try
End Sub

''' <summary>
''' Mengisi Combo Box kedua (countries)
''' </summary>
''' <param name="ContinentID"></param>
Private Sub FillComboCountries(ContinentID As Integer)
    ' siapkan variable koneksi database
    Dim cn As New SqlCeConnection(My.MySettings.Default.dbSampleConnectionString)
    Dim da As New SqlCeDataAdapter("SELECT * FROM Countries WHERE ContinentID=@p1", cn)
    ' siapkan data table untuk menampung data dari database
    Dim dt As New DataTable()
    ' selalu gunakan try-catch block
    Try
        ' isikan parameter Continent'Benua
        da.SelectCommand.Parameters.AddWithValue("@p1", ContinentID)
        ' isi dataset
        da.Fill(dt)
        ' binding dataset ke combobox kedua
        comboBox2.ValueMember = "ID"
        comboBox2.DisplayMember = "Name"
        comboBox2.DataSource = dt
    Catch ex As Exception
        ' infokan ke user, jika ada error
        MessageBox.Show(ex.Message)
    End Try
End Sub


''' <summary>
''' Mengisi Combo Box ketiga (cities)
''' </summary>
''' <param name="CountryID"></param>
Private Sub FillComboCities(CountryID As Integer)
    ' siapkan variable koneksi database
    Dim cn As New SqlCeConnection(My.MySettings.Default.dbSampleConnectionString)
    Dim da As New SqlCeDataAdapter("SELECT * FROM Cities WHERE CountryID=@p1", cn)
    ' siapkan data table untuk menampung data dari database
    Dim dt As New DataTable()
    ' selalu gunakan try-catch block
    Try
        ' isikan parameter Continent'Benua
        da.SelectCommand.Parameters.AddWithValue("@p1", CountryID)
        ' isi dataset
        da.Fill(dt)
        ' binding dataset ke combobox kedua
        comboBox3.ValueMember = "ID"
        comboBox3.DisplayMember = "Name"
        comboBox3.DataSource = dt
    Catch ex As Exception
        ' infokan ke user, jika ada error
        MessageBox.Show(ex.Message)
    End Try
End Sub

[/collapsed]

Sedangkan versi C# nya adalah sebagai berikut

[collapsed title=Pengambilan Data Versi C#]

    /// <summary>
    /// Mengisi Combo Box pertama (continents)
    /// </summary>
    private void FillComboContinents()
    {
        // siapkan variable koneksi database
        SqlCeConnection cn = new SqlCeConnection(Properties.Settings.Default.dbSampleConnectionString);
        SqlCeDataAdapter da = new SqlCeDataAdapter("SELECT * FROM Continents", cn);
        // siapkan data table untuk menampung data dari database
        DataTable dt = new DataTable();
        // selalu gunakan try-catch block
        try
        {
            // isi dataset
            da.Fill(dt);
            // binding dataset ke combobox pertama
            comboBox1.ValueMember = "ID";
            comboBox1.DisplayMember = "Name";
            comboBox1.DataSource = dt;
        }
        catch (Exception ex)
        {
            // infokan ke user, jika ada error
            MessageBox.Show(ex.Message);
        }
    }

    /// <summary>
    /// Mengisi Combo Box kedua (countries)
    /// </summary>
    /// <param name="ContinentID"></param>
    private void FillComboCountries(int ContinentID)
    {
        // siapkan variable koneksi database
        SqlCeConnection cn = new SqlCeConnection(Properties.Settings.Default.dbSampleConnectionString);
        SqlCeDataAdapter da = new SqlCeDataAdapter("SELECT * FROM Countries WHERE ContinentID=@p1", cn);
        // siapkan data table untuk menampung data dari database
        DataTable dt = new DataTable();
        // selalu gunakan try-catch block
        try
        {
            // isikan parameter Continent/Benua
            da.SelectCommand.Parameters.AddWithValue("@p1", ContinentID);
            // isi dataset
            da.Fill(dt);
            // binding dataset ke combobox kedua
            comboBox2.ValueMember = "ID";
            comboBox2.DisplayMember = "Name";
            comboBox2.DataSource = dt;
        }
        catch (Exception ex)
        {
            // infokan ke user, jika ada error
            MessageBox.Show(ex.Message);
        }
    }

    /// <summary>
    /// Mengisi Combo Box ketiga (cities)
    /// </summary>
    /// <param name="CountryID"></param>
    private void FillComboCities(int CountryID)
    {
        // siapkan variable koneksi database
        SqlCeConnection cn = new SqlCeConnection(Properties.Settings.Default.dbSampleConnectionString);
        SqlCeDataAdapter da = new SqlCeDataAdapter("SELECT * FROM Cities WHERE CountryID=@p1", cn);
        // siapkan data table untuk menampung data dari database
        DataTable dt = new DataTable();
        // selalu gunakan try-catch block
        try
        {
            // isikan parameter Continent/Benua
            da.SelectCommand.Parameters.AddWithValue("@p1", CountryID);
            // isi dataset
            da.Fill(dt);
            // binding dataset ke combobox ketiga
            comboBox3.ValueMember = "ID";
            comboBox3.DisplayMember = "Name";
            comboBox3.DataSource = dt;
        }
        catch (Exception ex)
        {
            // infokan ke user, jika ada error
            MessageBox.Show(ex.Message);
        }
    }

[/collapsed]

Menangkap Perubahan Pilihan Combo Box

Untuk menangkap perubahan pilihan pengguna, maka kita perlu mendeklarasikan beberapa event handler untuk menangani event SelectedValueChanged. Setiap kali ada perubahan di Combo Box yang berisikan data benua, maka otomatis event handler ini akan mengambil ID dari benua bersangkutan, kemudian memanggil fungsi FillCOmboCounteries yang sudah kita buat sebelumnya untuk mengisi combobox negara sesuai dengan pilihan benuanya. Logika yang sama diterapkan untuk combobox yang berisi data negara, otomatis fungsi FillComboCities akan dipanggil setiap kali ada perubahan pilihan negara. Implementasi pengambilan data dalam VB.net menjadi seperti ini,

[collapsed title=Menangkap Perubahan Pilihan Combo Box Versi VB.net]

''' <summary>
''' Form Constructor
''' Inisialisasi event handler dan mengisi combo box pertama
''' </summary>
''' <remarks></remarks>
Public Sub New()
    InitializeComponent()
    InitializeEventHandlers()
    FillComboContinents()
End Sub

''' <summary>
''' InitializeEventHandlers, menentukan event delegate 
''' untuk menangani event SelectedValueChanged setiap kali 
''' user memilih item baru di combo box pertama (continents)
''' dan memilih item baru di combo box kedua (countries)
''' </summary>
Private Sub InitializeEventHandlers()
    AddHandler comboBox1.SelectedValueChanged, AddressOf comboBox1_SelectedIndexChanged
    AddHandler comboBox2.SelectedValueChanged, AddressOf comboBox2_SelectedIndexChanged
End Sub

''' <summary>
''' Setiap kali user memilih benua baru, 
''' maka isi combo box kedua dengan negara yang sesuai
''' </summary>
Private Sub comboBox1_SelectedIndexChanged(sender As Object, e As EventArgs)
    '' pastikan pilihan benar
    If (Not IsNothing(comboBox1.SelectedValue)) Then
        '' ambil ID benua yang dipilih user
        Dim id As Integer = comboBox1.SelectedValue
        '' isi combobox country berdasarkan benua yang dipilih
        FillComboCountries(id)
    End If
End Sub

''' <summary>
''' Setiap kali user memilih negara baru, 
''' maka isi combo box ketiga dengan kota yang sesuai
''' </summary>
Private Sub comboBox2_SelectedIndexChanged(sender As Object, e As EventArgs)
    '' pastikan pilihan benar
    If (Not IsNothing(comboBox2.SelectedValue)) Then
        '' ambil ID benua yang dipilih user
        Dim id As Integer = comboBox2.SelectedValue
        '' isi combobox country berdasarkan benua yang dipilih
        FillComboCities(id)
    End If
End Sub

[/collapsed]

Dan implementasi pengambilan data dalam bahasa C# menjadi seperti ini,

[collapsed title=Menangkap Perubahan Pilihan Combo Box Versi C#]

/// <summary>
/// Form Constructor
/// Inisialisasi event handler dan mengisi combo box pertama
/// </summary>
public frmMain()
{
    InitializeComponent();
    InitializeEventHandlers();
    FillComboContinents();
}

/// <summary>
/// InitializeEventHandlers, menentukan event delegate 
/// untuk menangani event SelectedValueChanged setiap kali 
/// user memilih item baru di combo box pertama (continents)
/// dan memilih item baru di combo box kedua (countries)
/// </summary>
private void InitializeEventHandlers()
{
    comboBox1.SelectedValueChanged += new EventHandler(comboBox1_SelectedValueChanged);
    comboBox2.SelectedValueChanged += new EventHandler(comboBox2_SelectedValueChanged);
}

/// <summary>
/// Setiap kali user memilih benua baru, 
/// maka isi combo box kedua dengan negara yang sesuai
/// </summary>
void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
    // pastikan pilihan benar
    if (comboBox1.SelectedValue != null)
    {
        // ambil ID benua yang dipilih user
        int id = (int)comboBox1.SelectedValue;
        // isi combobox country berdasarkan benua yang dipilih
        FillComboCountries(id);
    }
}

/// <summary>
/// Setiap kali user memilih negara baru, 
/// maka isi combo box ketiga dengan kota yang sesuai
/// </summary>
void comboBox2_SelectedValueChanged(object sender, EventArgs e)
{
    // pastikan pilihan benar
    if (comboBox2.SelectedValue != null)
    {
        // ambil ID benua yang dipilih user
        int id = (int)comboBox2.SelectedValue;
        // isi combobox cities berdasarkan negara yang dipilih
        FillComboCities(id);
    }
}[/collapsed]

Hasil Akhir

Begini tampilan untuk pilihan negara sesuai benua

Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat

Dan ini tampilan kota sesuai dengan pilihan negara

Chained Dropdown List, atau Chained Combo Box, atau Chained Select, atau jika di Indonesiakan menjadi Select Bertingkat atau Combo Box Bertingkat

Source code silakan download di sini.

 

Leave a Reply

Your email address will not be published. Required fields are marked *