none
DataGridViewComboBoxColumn Selected Index Changed Problem

    Question

  • HI All,
             I am using VS05 + Windows Forms + c#.  In my application i have Gridview which contains two DataGridViewComboBoxColumn ie. cmbFertilizername,cmbfertilizertype. I want
    1) At Page Load Assign "Fertilizername" coumn from table "Fertilizer"  to first DataGridViewComboBoxColumn ie.cmbFertilizername
    2) When user select Fertilizer Name From First DataGridViewComboBoxColumn at that time according to Fertilizername ,assign FertilizerType to second DataGridViewComboBoxColumn ie.cmbfertilizertype.

    The Procedure in c# is appriciated.

    Thanks in advance.
    Wednesday, April 08, 2009 12:54 PM

All replies

  • Hi sunDAC,

    Use EditingControlShowing Event of Grid.

    Here is an example.  It's in VB.Net, convert it into C#.Net.



    If GridOptions.CurrentCell.ColumnIndex = GRID_OPTIONS_COLUMN_SUB_TYPE_SECONDARY Then // Checking Column Index.
         Dim cmb As ComboBox = TryCast(e.Control, ComboBox)
         Dim BSPolicySubType As New BindingSource  //Temp BindingSource for 2nd Combobox.
         BSPolicySubType.DataSource = oDB.GetVivaSubType(GridOptions.Item(GRID_OPTIONS_COLUMN_TYPE, GridOptions.CurrentRow.Index).Value).Tables(0) //Assigning New DataSource 
         With cmb
             .Width = 140
             .DataSource = BSPolicySubType.DataSource //New DataSource to Current Combobox.
             .ValueMember = "SubType_ID"
             .DisplayMember = "SubToken"
         End With
         GridOptions.Refresh()
    End If
    If you need more help, Let me know.



    Thank You.

    Best Regards,
    Utkarsh Gajjar.
    Utkarsh Gajjar
    Wednesday, April 08, 2009 4:58 PM
  • Hi Thanks for the reply,
              I have gone through the code.But I cant get on which event of Gridview actually i write above code.
    Can you provide sample procedure which contains
    1) Add Two DataGridViewComboBoxColumn in Gridview.
    2) Bind First DataGridViewComboBoxColumn  from databse at page load
    3) Bind second DataGridViewComboBoxColumn from first DataGridViewComboBoxColumn value.

    There is lot of Gridview events ,which i cant find. So the procedure will help me.

    Thank you.
    Thursday, April 09, 2009 4:34 AM
  • Hi SunDAC,

    The following is a complete code to get what you want. It requires that you add a DataGridView on the form and add two DataGridViewComboBoxColumn into the DataGridView. It also requires that you add a strong-typed DataSet named DataSet1 in the project and add three DataTable in the DataSet1. The names and definitions of these three DataTable are as follows:

    DataTable1  (ParentID System.Int32, ChildID System.Int32)
    ParentTable  (ParentID System.Int32 Unique, ParentName System.string)
    ChildTable    (ChildID System.Int32 Unique, ChildName System.string, ParentID System.Int32)

    The code in the form:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);
                this.dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
                this.dataGridView1.CellBeginEdit += new DataGridViewCellCancelEventHandler(dataGridView1_CellBeginEdit);
            }

            void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
            {
                // cancel editing if the ParentID has not been set
                if (e.ColumnIndex == 1 && this.dataGridView1.CurrentRow.Cells[0].FormattedValue.Equals(string.Empty))
                {
                    e.Cancel = true;
                }
            }

            void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
            {
                // reset the ChildID value if the ParentID value is changed
                if (e.ColumnIndex == 0)
                {
                    this.dataGridView1.CurrentRow.Cells[1].Value = DBNull.Value;
                }
            }

            void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
            {
                if (this.dataGridView1.CurrentCell.ColumnIndex == 1)
                {
                    ComboBox cmb = e.Control as ComboBox;
                    BindingSource tempBS = new BindingSource(ds, "ChildTable");              
                    tempBS.Filter = "ParentID =" + this.dataGridView1.CurrentRow.Cells[0].Value;
                    cmb.DataSource = tempBS;
                    cmb.DisplayMember = "ChildName";
                    cmb.ValueMember = "ChildID";
                }
            }

          
            DataSet1 ds = new DataSet1();
            private void Form1_Load(object sender, EventArgs e)
            {           
                this.dataGridView1.AutoGenerateColumns = false;
                this.dataGridView1.DataSource = ds;
                this.dataGridView1.DataMember = "DataTable1";
                this.Column1.DataPropertyName = "ParentID";
                this.Column2.DataPropertyName = "ChildID";

                // populate the ParentTable and the ChildTable
                ds.ParentTable.Rows.Add(new object[] { 1, "A" });
                ds.ParentTable.Rows.Add(new object[] { 2, "B" });

                ds.ChildTable.Rows.Add(new object[] { 1, "A-a", 1 });
                ds.ChildTable.Rows.Add(new object[] { 2, "A-b", 1 });
                ds.ChildTable.Rows.Add(new object[] { 3, "B-c", 2 });
                ds.ChildTable.Rows.Add(new object[] { 4, "B-d", 2 });            
               
                this.Column1.DataSource = ds.ParentTable;
                this.Column1.DisplayMember = "ParentName";
                this.Column1.ValueMember = "ParentID";

                this.Column2.DataSource = ds.ChildTable;
                this.Column2.DisplayMember = "ChildName";
                this.Column2.ValueMember = "ChildID";
            } 
        }

    This code works fine on my side. Please try it to see if there's any question.

    If you have any question, please feel free to let me know.

    Sincerely,
    Linda Liu

    • Marked as answer by Linda Liu Thursday, April 16, 2009 2:13 AM
    • Unmarked as answer by sunDAC Wednesday, April 22, 2009 9:26 AM
    Tuesday, April 14, 2009 5:17 AM
  • Hi Linda Liu,
                       Thanks for the reply. I have gone through the code. I have created a strong-typed DataSet named DataSet1 in the project and add three DataTable in the DataSet1 as per the suggestions.


    But it give me error at below event as  {"Object reference not set to an instance of an object."}
    void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
            {
                // reset the ChildID value if the ParentID value is changed
                if (e.ColumnIndex == 0)
                {
                    this.dataGridView1.CurrentRow.Cells[1].Value = DBNull.Value;
                }
            }

    I have commented above code and the application run quite good. Means when select value from one Cobobox according to the value of combobox second combobox is filled.

    But all this stuff is done when all the data from DataSet1,DataTable is hardcode . I want to pass value to ParentTable,ChildTable dynamically.  so that i use these tables as per the requirements. How to do this?

    In short i want to fill the two Combobox Dynamically ie.The values should fetch from database.
    Hope so you get my point.

    Thanks.
    Wednesday, April 15, 2009 6:16 AM
  • Hi SunDAC,

    > In short i want to fill the two Combobox Dynamically ie.The values should fetch from database.

    In my previous sample, I populate the parent DataTable and the child DataTable manually just for demonstration.
    In  your practice, you can use DataAdapter or TableAdapter to retrieve data from DB and fill the data into the parent DataTable and child DataTable.

    If you have anything unclear, please feel free to let me know.

    Sincerely,
    Linda Liu
    Wednesday, April 15, 2009 7:07 AM
  • Hi Thanks for the reply,
              I have gone through the code.But I cant get on which event of Gridview actually i write above code.
    Can you provide sample procedure which contains
    1) Add Two DataGridViewComboBoxColumn in Gridview.
    2) Bind First DataGridViewComboBoxColumn  from databse at page load
    3) Bind second DataGridViewComboBoxColumn from first DataGridViewComboBoxColumn value.

    There is lot of Gridview events ,which i cant find. So the procedure will help me.

    Thank you.

    On EditingControlShowing Event


    Thank You.

    Best Regards
    Utkarsh Gajjar.

    Utkarsh Gajjar
    Wednesday, April 15, 2009 1:43 PM
  • HI Linda Liu,
                      Sorry for the late reply.
    I have two DataGridViewComboBoxColumn namely cmbSiteName,cmbPlotName.
    At page load i have fill value of  "Sitename" from database and assign the datasource to cmbSiteName.
    Now when User select SiteName from cmbSiteName  DataGridViewComboBoxColumn at that time i want to fill "PlotName" and assign that datasource to cmbPlotName  DataGridViewComboBoxColumn .

    at page load function funFillGrid() is called.
    gvPlotInformation is name of my Gridview.
     getPlotName(mid); is the function which gets all the Plot information from databse . Which is working fine.


     

    private void funFillGrid()

    {

    try
    {
    DataGridViewComboBoxColumn cmbSiteName = new DataGridViewComboBoxColumn(); cmbSiteName.HeaderText = "Site Name";
    cmbSiteName.Name =
    "SiteName";
    cmbSiteName.DisplayMember =
    "site_number";
    cmbSiteName.ValueMember =
    "srNo";
    cmbSiteName.Width = 150;
    cmbSiteName.DisplayStyle =
    DataGridViewComboBoxDisplayStyle.DropDownButton;

    DataSet ds = new DataSet();
    //Function call to get Plot name
    ds = objPlot.getPlotName(mid);

    DataTable dt = ds.Tables[0];
    DataRow dr = dt.NewRow();
    dr[
    "site_number"] = "Select";
    dr[
    "srNo"] = "0";
    dt.Rows.InsertAt(dr, 0);
    cmbSiteName.DataSource = dt;
    cmbSiteName.DefaultCellStyle.NullValue =
    "Select";
    gvPlotInformation.Columns.Insert(0, cmbSiteName);

    cmbPlotName =

    new DataGridViewComboBoxColumn();
    cmbPlotName.HeaderText =
    "Plot Name";
    cmbPlotName.Name =
    "PlotName";
    gvPlotInformation.Columns.Insert(1, cmbPlotName);

     

    //Add new row
    gvPlotInformation.Rows.Add();

    }

    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    }

    //***************Here I am trying to get Plot information from SiteName
    private void gvPlotInformation_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
    try
    {
    //*************** Fill Plot Name for Site
    if (gvPlotInformation.Columns[this.gvPlotInformation.CurrentCell.ColumnIndex].Name.Equals("SiteName") && e.Control is ComboBox)
    {
    if (gvPlotInformation.CurrentRow.Cells["SiteName"].Value == null)
    {
    MessageBox.Show("Please select Site name");
    return;
    }
    else
    {
    int iSiteName = Convert.ToInt32(gvPlotInformation["SiteName", gvPlotInformation.CurrentCell.RowIndex].Value.ToString());

    //*************** Function to Fill Plot Information
    DataSet ds = objPlot.getPlotInformation(iSiteName, mid);
    BindingSource tempBS = new BindingSource(ds, "site_plots");   //site_plots is name of table from where i fetch Plot Name

    cmbPlotName.Width = 140;
    cmbPlotName.DataSource = tempBS;
    cmbPlotName.ValueMember =

    "plot_name";
    cmbPlotName.DisplayMember =
    "plot_name";
    }
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.ToString());
    }
    }


    But it cant get work.

    What changes i have to do here?
    Thank you.

    Wednesday, April 22, 2009 9:22 AM
  • Hi SunDAC,

    I see you set the DataSource of the Plot combobox column dynamically. You should avoid doing like that because it will cause an exception if there's a value under the Plot combobox column but this value isn't contained in the data source of the Plot combobox column.

    For example, if a cell under the Plot column has a value of "a", but the data source of this column doesn't contain the value "a", an exception will occur "system.ArgumentException:DataGridViewComboBoxCell value is not valid".

    I suggest that you fill all the Plot data into a DataTable and set the DataSource of the Plot column to it. In the EditingControlEditing event handler, change the data source of the editing control (combobox). Please try my sample code in my previous reply. It works fine on my side.

    Sincerely,
    Linda Liu

    Friday, April 24, 2009 10:19 AM
  • HI Linda Liu,
                         THanks for the reply. I have follow the procedure you given.

    1) i have created strong-typed DataSet named DataSet1 as below
    DataTable1  (SiteId System.Int32, PlotId System.Int32)
    SIteTable  (SiteId System.Int32 Unique, SiteName System.string)
    PlotTable    (PlotId System.Int32 Unique, PlotName System.string, SiteId System.Int32)

    2) Below is the total code which i have used. SiteName and PlotName is my Columns name from Gridview.
    getSiteName is the function which is used to get all site name.getPlotName is Function which is used to get All Plot Name. These functions are working fine.

     

    DataSet1 ds = new DataSet1();

     

    private void frmSantosh_Load(object sender, EventArgs e)
    {
    try
    {
    this.gvPlotInformation.AutoGenerateColumns = false;
    this.gvPlotInformation.DataSource = ds;
    this.gvPlotInformation.DataMember = "DataTable1";
    this.SiteName.DataPropertyName = "SiteId";
    this.PlotName.DataPropertyName = "PlotId";

    DataSet dsSiteName = objPlot.getSiteName(mid);
    for (int i = 0; i < dsSiteName.Tables[0].Rows.Count; i++)
    {
    ds.SIteTable.Rows.Add(
    new object[] { Convert.ToInt32(dsSiteName.Tables[0].Rows[i]["srNo"].ToString()), dsSiteName.Tables[0].Rows[i]["site_name"].ToString() });
    }

     

    DataSet dsPlotName = objPlot.getPlotName(mid);
    for (int i = 0; i < dsPlotName.Tables[0].Rows.Count; i++)
    {
    ds.PlotTable.Rows.Add(
    new object[] { Convert.ToInt32(dsPlotName.Tables[0].Rows[i]["srNo"].ToString()), dsPlotName.Tables[0].Rows[i]["plot_name"].ToString(), Convert.ToInt32(dsPlotName.Tables[0].Rows[i]["site_name"].ToString()) });
    }

     

    this.SiteName.DataSource = ds.SIteTable;
    this.SiteName.DisplayMember = "SiteName";
    this.SiteName.ValueMember = "SiteId";
    this.PlotName.DataSource = ds.PlotTable;
    this.PlotName.DisplayMember = "PlotName";
    this.PlotName.ValueMember = "PlotId";
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    }

     

    private void gvPlotInformation_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
    {
    try
    {
    // cancel editing if the ParentID has not been set
    if (e.ColumnIndex == 1 && this.gvPlotInformation.CurrentRow.Cells[0].FormattedValue.Equals(string.Empty))
    {
    e.Cancel =
    true;
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.ToString());
    }
    }

     

    private void gvPlotInformation_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
    try
    {
    // reset the ChildID value if the ParentID value is changed
    if (e.ColumnIndex == 0)
    {
    this.gvPlotInformation.CurrentRow.Cells[1].Value = DBNull.Value;
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.ToString());
    }
    }

     

    private void gvPlotInformation_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
    try
    {
    if (this.gvPlotInformation.CurrentCell.ColumnIndex == 1)
    {
    ComboBox cmb = e.Control as ComboBox;
    BindingSource tempBS = new BindingSource(ds, "PlotTable");
    tempBS.Filter =
    "SiteId =" + this.gvPlotInformation.CurrentRow.Cells[0].Value;
    cmb.DataSource = tempBS;
    cmb.DisplayMember =
    "PlotName";
    cmb.ValueMember =
    "PlotId";
    }
    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.ToString());
    }
    }


    There are some issues regarding this code.
    1) When i start aplication at that time i get error,
    System.NullReferenceException: Object reference not set to an instance of an object
    gvPlotInformation_CellValueChanged(Object sender, DataGridViewCellEventArgs e)

    2) When i Select SiteName as "san" at that moment i like to fill PlotName combobox as "Plot1" .
    ie. When i select sitename at that select index change fill Plotname combobox.

    3)   Here what happesns when i select one site name and then click on Plotname at that time that combobox is filed. Again when i select Sitename at that moment the plotname is not filled instantly.

    I want help regarding
    1) why there is error for gvPlotInformation_CellValueChanged(Object sender, DataGridViewCellEventArgs e)

    2) Is it not possible to use Selectindex change event of sitename comobox so that at that time instantly the ploname is get filled.

    What changes i have to do here?

    Thank you.
    Friday, April 24, 2009 12:34 PM
  • HI Linda Liu,
              The procedure which i follow gives following Result,
    1) When i select Site1 at that time second Combobbox when hit gives result Plot1
    2)When i select Site2 at that time second Combobbox when hit gives result Plot2

    But again when i select Site1 and not hit second ComboBox at that time Second Combobox is still fill with Plot2,which is a wrong result.
    I want
    1)when select Site1 at that time at the selected index change event of First Combobox,the second ComboBox should filled with "Plot1"
    2) When select Site2 then fill with Plot2.

    For the above result what changes i have to do?

    Thank You.

    Tuesday, April 28, 2009 4:49 AM