简体   繁体   中英

Binding ComboBox to DataTable (WinForms c#)?

I have a method which populates my ComboBox from a DataTable :

public string populateCompanyTransSellingEntityLookUp(ref System.Windows.Forms.ComboBox Combo, string Id, Contract Contract)
    {
        SqlCommand _comm = new SqlCommand();
        _comm.Parameters.AddWithValue("@id", Id);
        _comm.CommandText = "SELECT [name] FROM dbo.fnGetList(@id) ORDER BY [name]; ";   
        _comm.Connection = _conn;
        _comm.CommandTimeout = _command_timeout;

        DataTable dt = new DataTable();
        try
        {
            SqlDataReader myReader = _comm.ExecuteReader();
            dt.Load(myReader);

            Combo.DataSource = dt;
            Combo.DisplayMember = "name";

            foreach (DataRow dr in dt.Rows)
            {
                if (dr["name"].ToString() == Contract.Company_Name.ToString())
                {                        
                    Combo.Text = dr["company_int_name"].ToString();
                }
            }
        }
        catch
        {
            MessageBox.Show("Unable to populate Company Name LookUp");
        }


        return "";
    }

I'm passing my saved value Contract.Company_Name into the forEach loop to find my required SelectedItem from the DataTable . The ComboBox is populated with my DataTable values from Combo.Datasource =dt; but my selected item isn't being set. The code compiles without exception. If I remove Datasource = dt;, the SelectedItem is set no problem. Why is the is set no problem. Why is the Datasource overriding my SelectedItem` and is there something I've missed with my binding?

Thanks all

尝试这个:

Combo.SelectedItem = dr;

At first you have to set the valueMember for sure. Then you can set the selectedValue Property instead of SelectedItem. The Item is one datasource record. So in your case it would be SelectedItem = dr ! But iam not sure this is working.

I would suggest to use SelectedValue , then you don't need to loop through values "manually".

Also you don't need to use "heavy-weight" DataTable where you need just a collection of string values.

private IEnumerable<string> LoadNames(string id)
{
    var query = "SELECT [name] FROM dbo.fnGetList(@id) ORDER BY [name]";

    using (var connection = new SqlConnection("connectionString")
    using (var command = new SqlCommand(query, connection)
    {
        // 36 is the size of the VarChar column in database(use your value)
        command.Parameters.Add("@id", SqlDbType.VarChar, 36).Value = id;

        connection.Open();
        using (var reader = command.ExecuteReader())
        {
            var names = new List<string>();
            while(reader.Read())
            {
                names.Add(reader.GetString(0));
            }

            return names;
        }
    }
}


public void Populate(ComboBox combobox, string id, Contract contract)
{
    combobox.DataSource = LoadNames(id);
    combobox.SelectedValue = contract.Copmpany_Name.ToString();
}

Few things to notice:

  1. Dispose all objects which dealing with external resources ( SqlConnection , SqlCommand and SqlDataReader )
  2. Create SqlParameter with precise information about the type, for strings is important to provide size of the column in database. This information will improve SQL query performance on server side.
  3. Don't pass combobox as a reference, populate method does not create new instance but only consume the given ComboBox instance.

Thank you for the help, I edited the code given that my problem was much more trivial.

public string populate_comboBox(ref System.Windows.Forms.ComboBox Combo)
    {
        SqlCommand _comm = new SqlCommand();

        //edited for a simple one column sql query 
        _comm.CommandText ="SELECT [Column] FROM dbo.SQL_Table ORDER BY [Column];";
        //MUST open sql connection to DB 
        SqlConnection conn = new SqlConnection(global_DB_String_Connection);
        conn.Open();
        _comm.Connection = conn;

        DataTable dt = new DataTable();
        try
        {
            SqlDataReader myReader = _comm.ExecuteReader();
            dt.Load(myReader);

            Combo.DataSource = dt;
            Combo.DisplayMember = "ColumnName";

            foreach (DataRow dr in dt.Rows)
            {
                //populates the combo box with query results
                Combo.Text = dr["ColumnName"].ToString();
            }
        }
        catch
        {
            Console.WriteLine("ComboBox Populate method has failed! ");
        }
        conn.Close();
        return "";
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM