Problem with combobox

Hi

I have a datagridview that is databound to a table via a bindingsource and a DataGridViewComboBox column that is bound to a second table (both in the same dataset). I am dynamically adding the column to the grid. 

Dim viewcol As New DataGridViewComboBoxColumnviewcol.DataSource = _dsEquivalents.Tables(1)
viewcol.DataPropertyName =
"ViewName"
viewcol.ValueMember = "ViewTable"
viewcol.DisplayMember = "ViewTable"
viewcol.HeaderText = "View Name"
viewcol.AutoComplete = False
dgvEqu.Columns.Add(viewcol)

BindingSource1.DataSource = m_dsEquivalents
BindingSource1.DataMember = m_dsEquivalents.Tables(0).TableName


The table bound to the grid contains values that are not in the table bound to the combo. This causes an Dataerror which I trap but the value still doesnt display in the grid. Do I need to do an ovverride I would also like to be able to type values into the cell that are not in the combobox is this possible
 



Answer this question

Problem with combobox

  • wsauer

    couple of things:

    1) seems that with every EditingControlShowing event an Additional handler is added and they build up.  Shouldn't the tail end of cbo_Validating have:
    cbo.Validating -= new CancelEventHandler(cbo_Validating);
    added so that cbo_Validating only executes once per EditingControlShowing event
    when i add a trace to check the number of times cbo_Validating fires the number keeps getting higher ... maybe i implemented it different than you...

    2) intermittantly I'm still getting the data error.  not every time, but enough that I notice. And when I'm getting the error it seems that the data_error event is raised before the cbo.Validating event.  I'm starting to think about adding the item in .cellValidating as it executes before .DataError event

    what do you think

    /gabe


  • Faris Mlaeb

    Thanks  again.
  • Work2

    The DataGridView raises a DataError when the value is not in the ComboBox's list.  To display the value, you must add the value to the ComboBox.  The other option is to create your own combobox column.

    There must not be a foreign key relationship between your two tables, or else you wouldn't be having this problem.  How were you going to have users enter data not in the combobox   It seems like you are looking for the ComboBoxStyle.DropDownList behaviour in DataGridViewComboBoxColumn.   What follows is an example of how to accomplish this.

    The ComboBox used by the DataGridViewComboBoxColumn has a DropDownStyle property set to ComboBoxStyle.DropDownList, but DataGridViewComboBoxColumn does not expose this property, so out-of-box there is no way to type text into a combobox column.  You can change this by handling the EditingControlShowing event, and setting the DropDownStyle:


    void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)

    {

    if (e.Control.GetType() == typeof(DataGridViewComboBoxEditingControl))

    {

    DataGridViewComboBoxEditingControl cbo = e.Control as DataGridViewComboBoxEditingControl;

    cbo.DropDownStyle = ComboBoxStyle.DropDown;

    cbo.Validating += new CancelEventHandler(cbo_Validating);

    }

    }


     



    In this example, all ComboBox columns will have the DropDownStyle property set to DropDown.  In addition, handle validating to add user-typed items to the list.



    void cbo_Validating(object sender, CancelEventArgs e)

    {

    DataGridViewComboBoxEditingControl cbo = sender as DataGridViewComboBoxEditingControl;

    DataGridView grid = cbo.EditingControlDataGridView;

    object value = cbo.Text;

    // Add value to list if not there

    if (cbo.Items.IndexOf(value) == -1)

    {

    DataGridViewComboBoxColumn cboCol = grid.Columns[grid.CurrentCell.ColumnIndex] as DataGridViewComboBoxColumn;

    // Must add to both the current combobox as well as the template, to avoid duplicate entries...

    cbo.Items.Add(value);

    cboCol.Items.Add(value);

    grid.CurrentCell.Value = value;

    }

    }


     


  • Dusty21269

    Hi Durstin,
                    In your post you said:
    >    "The other option is to create your own combobox column."

    Any chance you could give me a quick run through on how to do this I presume it would mean inheriting from DataGridViewComboBoxColumn which in turn would mean inheriting from DataGridViewComboBoxCell in order to get access to the editing control. What method in
    DataGridViewComboBoxCell would I have to override in order to ensure any data which is not in the combo box's datasource is still drawn

    I hope this makes sense!, if not I will try and explain it better.

    Thanks,
    Cathal.

  • Niky

    My reply is to the origianl post and also that which explians the cause of the error as a value not in the list of items in the combobox column.

    First I have the same problem as originally stated. I'm convinced that the combobox column property DataPropertyName is not set to something valid - in fact the DataSource for the box seems to supply info from only one table - it is after set to a single DataTable object.

    As for values not being in the dropdownlist, I agree its a problem, but in a parent/chaild table, the re will be FK's in the parent table that are NULL. This should not cause an error. It certainly doesn't in the normal Combobox control. I have both on a single form and the normal combobox works fine from the same two tables all because it can be bound to both tables through data bindings. The combobox column doesn't have that ability.

  • Oso Hada

    A thought for you Raju.

    Check to see if the DisplayStyle for the column is DropDownButton
    and the DisplayStyleForCurrentCellOnly is false.


  • tehlike

    hi,
    i have the same situation like in the first post. I tryed to bound the combobox via
    smart tag and manually in the formattingcell event. I bounded it to a dataset,datatable,dataview,arraylist. it always raises an dataerror.(wrong value)

    please give me an example how to bind the box to one column of my datatable.

    thanx

  • Kaishain

    Hi,

    I have copied this code but I get this error:

    "No se puede modificar la coleccion Items cuando esta establecida la propiedad DataSource."

    in

    cmb.Items.Add(value)

    I fill the comboboxcolumn from a database and I belive that this is the problem. How can I solve it


    Thanks

  • melcom

    http://www.windowsforms.net/Samples/Go%20To%20Market/DataGridView/DataGridView%20FAQ.doc

    seemed to answer the vast majority of the problems i had.  if that doesn't lead you to the solution repost and i'll put together a sample

    gabe

  • JDL440

    First, I can't read much else but English, so I don't understand your question.

    Second...In many other posts of mine and others' its become clear that the DataGridView Combobox control is incomplete. It needs the capability to bind to two tables in a dataset. The normal combobox control has this ability through its databinding collection. The current DGV Combobox gives all of us roughly the same errors for very much the same reasons.

  • Keyboard_Cowboy

    Hi mafc,

    I'm guessing your problem is you have bound the DataSource property. Instead, set DataSource to "none" and fill the combo's Items collection in the Form_Load event. Here is sample code from my previous post in this thread to do this:

    Me.MyTableAdapter.Fill(Me.MyDataSet.MyList)

    MyDataGridViewComboBox.Items.Clear() 'This probably isn't necessary if done in the Load.

    'fill combobox

    Dim row As DataRow

    For Each row In Me.MyDataSet.MyList

    MyDataGridViewComboBox.Items.Add(row.Item(0))

    Next

    Hope that helps!


  • H. Feijt


    Yes this is my problem, but I don't know how to use your example in my code. My code is this :

    dim column_combo As DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn()
    .....

    SQL = "select CANT_NOMBRE from T_CANTIDADES"

    Dim dbDataSet_Cantidades As New Data.DataSet
    Dim tabla_Cantidades As New DataTable

    Try
    dbDataSet_Cantidades.Clear()

    dbDataAdapter = New FirebirdSql.Data.FirebirdClient.FbDataAdapter(SQL, FbConnection)
    dbDataAdapter.Fill(dbDataSet_Cantidades)

    tabla_Cantidades = dbDataSet_Cantidades.Tables(0)

    Catch ex As Exception ' catches any error

    MsgBox("Ha fallado al rellenar la columna cantidad")
    Finally
    End Try

    With column_combo

    .DataSource = tabla_Cantidades
    .ValueMember = "CANT_NOMBRE"
    .DisplayMember = .ValueMember
    .......
    .DataPropertyName = "CANTIDAD"
    .HeaderText = "CANTIDAD"
    .HeaderCell.Value = "CANTIDAD"

    End With

    Me.DGV_Recetas.Columns.Add(column_combo)

    Can I incorporate your code in the mine.

    Thanks



  • PCHOU

    hi,

    in my program i have used one combobox . when i desing this combobox that time this is ok but now this combo is look transperent how it happened when i click on combo then it look like combo with item list but at first time when programe started it will like textbox with out border. i put another combo but it is like old one . this effect is show in this project only if i working another project then combo is like good. if you say then i send you this splash screen with this combo.

    please give me solutional for this problem.

    raju



  • Stephie

    I pieced together helpful code from this thread and other sources, translated them to VB.NET and enhanced it to work for ALL comboboxes in the DataGridView. These routines should make the comboboxes editable, i.e., allow users to enter new values. (I also included commented out code that limits it to a specific combobox.)

    VB programmers should be able to copy and paste this code and just change "MyDataGridView" to the name of their DataGridView. (If you uncomment the code that uses "MyDataGridViewComboBox", you will need to change that to the name of your combobox.)

    This assumes that the combobox list is not bound to a datasource, but filled in the Form_Load event. This needs to be done for each combobox in the DataGridView. Here is a sample:

    'TODO: This line of code loads data into the 'MyDataSet.MyList' table. You can move, or remove it, as needed.

    Me.MyTableAdapter.Fill(Me.MyDataSet.MyList)

    MyDataGridViewComboBox.Items.Clear() 'This probably isn't necessary if done in the Load.

    'fill combobox

    Dim row As DataRow

    For Each row In Me.MyDataSet.MyList

    MyDataGridViewComboBox.Items.Add(row.Item(0))

    Next

    VB programmers should be able to copy and paste the rest of this code and just change "MyDataGridView" to the name of their DataGridView. (If you uncomment the code that uses "MyDataGridViewComboBox", you will need to change that to the name of your combobox.)

    Private Sub MyDataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles MyDataGridView.EditingControlShowing

    'Allow user to enter new values for ALL DataGridViewComboBox controls in the DataGridView

    If (TypeOf e.Control Is DataGridViewComboBoxEditingControl) Then

    Dim cmb As DataGridViewComboBoxEditingControl = CType(e.Control, DataGridViewComboBoxEditingControl)

    If Not cmb Is Nothing Then

    cmb.DropDownStyle = ComboBoxStyle.DropDown

    End If

    End If

    'Following Works for a specific combobox ///////////

    'If MyDataGridView.CurrentCellAddress.X = MyDataGridViewComboBox.DisplayIndex Then

    ' Dim cmb As ComboBox = CType(e.Control, ComboBox)

    ' If Not cmb Is Nothing Then

    ' cmb.DropDownStyle = ComboBoxStyle.DropDown

    ' End If

    'End If

    End Sub

    Private Sub MyDataGridView_CellValidating(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellValidatingEventArgs) Handles MyDataGridView.CellValidating

    'Allow user to enter new values for all DataGridViewComboBox controls in the DataGridView

    If (TypeOf CType(sender, DataGridView).EditingControl Is DataGridViewComboBoxEditingControl) Then

    Dim cmb As DataGridViewComboBoxEditingControl = CType(CType(sender, DataGridView).EditingControl, DataGridViewComboBoxEditingControl)

    If Not cmb Is Nothing Then

    Dim grid As DataGridView = cmb.EditingControlDataGridView

    Dim value As Object = cmb.Text

    '// Add value to list if not there

    If cmb.Items.IndexOf(value) = -1 Then

    '// Must add to both the current combobox as well as the template, to avoid duplicate entries...

    cmb.Items.Add(value)

    Dim cmbCol As DataGridViewComboBoxColumn = CType(grid.Columns(grid.CurrentCell.ColumnIndex), DataGridViewComboBoxColumn)

    If Not cmbCol Is Nothing Then

    cmbCol.Items.Add(value)

    End If

    End If

    grid.CurrentCell.Value = value

    End If

    End If

    ''Following Works for a specific combobox ///////////

    'If e.ColumnIndex = MyDataGridView.Columns("DataGridViewComboBoxColSize").Index Then 'CType(sender, DataGridView).CurrentCell.ColumnIndex

    ' 'Dim cmb As ComboBox = CType(e.Control, ComboBox)

    ' Dim cmb As DataGridViewComboBoxEditingControl = CType(CType(sender, DataGridView).EditingControl, DataGridViewComboBoxEditingControl)

    ' If Not cmb Is Nothing Then

    ' Dim grid As DataGridView = cmb.EditingControlDataGridView

    ' Dim value As Object = cmb.Text

    ' '// Add value to list if not there

    ' If cmb.Items.IndexOf(value) = -1 Then

    ' '// Must add to both the current combobox as well as the template, to avoid duplicate entries...

    ' cmb.Items.Add(value)

    ' Dim cmbCol As DataGridViewComboBoxColumn = CType(grid.Columns(grid.CurrentCell.ColumnIndex), DataGridViewComboBoxColumn)

    ' If Not cmbCol Is Nothing Then

    ' cmbCol.Items.Add(value)

    ' End If

    ' grid.CurrentCell.Value = value

    ' End If

    ' End If

    'End If

    ''//////////

    End Sub

    Private Sub MyDataGridView_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles MyDataGridView.DataError

    'I don't know if this is really necessary.

    If e.Exception.Message = "DataGridViewComboBoxCell value is not valid." Then

    e.Cancel = True

    End If

    End Sub


  • Problem with combobox