DataGridViewComboBox value is not valid? - c#

I keep getting an error that states DataGridViewComboBox value is not valid. It seems like it is also in an endless loop: I will click ok and it will continuously keep popping up. I am running a program with a windows form application written in C# and .NET. Does anyone know how to fix this error?
Here is some portions of my code:
// authorityTypeDataGridViewTextBoxColumn
//
this.authorityTypeDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.DisplayedCells;
this.authorityTypeDataGridViewTextBoxColumn.DataPropertyName = "AuthorityType";
this.authorityTypeDataGridViewTextBoxColumn.DataSource = this.AuthorityTypeBindingSource;
this.authorityTypeDataGridViewTextBoxColumn.DisplayMember = "Description";
this.authorityTypeDataGridViewTextBoxColumn.DisplayStyle = System.Windows.Forms.DataGridViewComboBoxDisplayStyle.ComboBox;
this.authorityTypeDataGridViewTextBoxColumn.Frozen = true;
this.authorityTypeDataGridViewTextBoxColumn.HeaderText = "AuthorityType";
this.authorityTypeDataGridViewTextBoxColumn.MaxDropDownItems = 100;
this.authorityTypeDataGridViewTextBoxColumn.Name = "authorityTypeDataGridViewTextBoxColumn";
this.authorityTypeDataGridViewTextBoxColumn.Resizable = System.Windows.Forms.DataGridViewTriState.True;
this.authorityTypeDataGridViewTextBoxColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
this.authorityTypeDataGridViewTextBoxColumn.ValueMember = "Value";
this.authorityTypeDataGridViewTextBoxColumn.Width = 121;
//
// AuthorityTypeBindingSource
//
this.AuthorityTypeBindingSource.DataMember = "AuthorityType";
this.AuthorityTypeBindingSource.DataSource = this.lookUpDataSet;
Does anyone have any suggestions?
Here is the Handler:
private void TaskSummaryGrid_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
MessageBox.Show(this, e.Exception.Message);
e.Cancel = true;
}

yeah the solution is to make datagridviewcombobox cell value the same you are getting in the code behind.
if i want to show typeof(int) value , i must set property of the datagridviewcombobox cell like:
this.ComboboxCellcolumnName.ValueType = typeof(int);
the value type that you got(e.g int) should be the same you want to show in the combobox cell (int).

It looks like your DataGridViewTextBoxColumn at some point was a DataGridViewComboBoxColumn, because you have ComboBox properties that do not belong to a TextBox column.
The DataGridViewTextBoxColumn does not have:
.DataSource = this.AuthorityTypeBindingSource;
.DisplayMember = "Description";
.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
.MaxDropDownItems = 100;
.ValueMember = "Value";
I can only guess editing the designer file by hand can cause this.

If, however, you wanted to revert back to your combo box column, you would need to set some special handling to set it up.
You can refer to the MSDN article here, or this example below:
MSDN: Binding Enums to DataGridViews
InitializeComponent();
// special setup for enum column
DataGridViewComboBoxColumn stateColumn = dgLedger.Columns[0] as DataGridViewComboBoxColumn;
if (stateColumn != null)
{
stateColumn.DataSource = Enum.GetValues(typeof(TransactionState));
}
_ledger = new BindingList<LedgerItem>();
dgLedger.DataSource = _ledger;

I just had a similar experience with one of my datagridviews: DataError was getting thrown non-stop... It eventually turned out to be because the id in the combobox DataSource was of a different type (bigint) than the column that referenced it (int)...

I used all the solution above but none of them worked, so I tried to override the DataError event and it works very well without any problem:
private void dgv_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
//do nothing
}

Ten years later now, I recently ran into the same problem and ended up working through the datagridview combobox source code to understand the problem and the solution. It turns out that even though swallowing error events is rarely the right course, #mamoun was correct: capturing the error and discarding it may be the correct solution in some scenarios. Here's why.
In a DataGridView with a ComboBox column, when grid data is loaded and the data in the grid column bound to the combobox value cannot be validated, a data error event is raised.
This can be tricky because the comboBox value is bound to a column in the DGV that may not be the same column in which the combobox itself appears (e.g., it may be a hidden column or another column that reflects the combobox value).
Validation can fail due to dev errors such as type mismatch, of course, but a common reason for failure is a scenario in which the dropdown data source is fixed (non-editable and does not allow adding new rows) and the datasource has delivered data in the value column that does not match any existing entry in the dropdown. This may occur, for example, if some of the data was originally entered as free-text and was misspelled, or if data is round-tripping to another system that changes white space or capitalization. It may occur if you change the list feeding the dropdown.
In this scenario, catching and ignoring (or preferably logging) the event will cause the value that triggered the error to be replaced with the default value from the combobox (usually the first row of the dropdown). If this is the desired handling, swallow away!
I wasn't able to find another event that allowed detection and correction to be carried out before the error event fires. In particular, the CellValidating event does not fire in this scenario.

Related

Exception setcurrentcelladdresscore thrown changing rows

I'm trying to replicate this behavior in the ColumnMappings window from SQL Management Studio:
Image Here
When you click inside a destination cell, the type changes from text
to combobox (it seems), and when you leave the cell, it takes the selected value from the combobox and changes back to textboxCell with the value included.
It does this for every cell in that column.
So, when I load the data, all the cells are textbox, and when the user enters any cell in that column, I do this:
private void dgvwMapping_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 1)
{
string txt = dgvwMapping[e.ColumnIndex, e.RowIndex].Value.ToString();
DataGridViewComboBoxCell cbbxDestination = new DataGridViewComboBoxCell() { DataSource = new List<string>(someList) };
cbbxDestination.Value = txt;
dgvwMapping[e.ColumnIndex, e.RowIndex] = cbbxDestination;
}
}
So far so good, if I change from cell to cell everything goes fine, except when I click the cell that has the coordinates [1,1]. The only one that throws the "Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore" exception is the one with the columnIndex equal to the rowIndex.
I already tried wrapping the line where I reassign the Cell Type in an invoke call, like this:
dgvwMapping.BeginInvoke(new MethodInvoker(delegate ()
{
dgvwMapping[e.ColumnIndex, e.RowIndex] = cbbxDestination;
}));
But It loops indefinitely the event. Even wrapping all the code inside the event makes the event loop indefinitely.
I haven't coded anything inside the CellEndEdit or the CellLeave yet.
Does anyone have any advice? Perhaps my aproach at replicating that behavior is not the best.
Thanks
Your issue:
When you click inside a destination cell, the type changes from text to combobox (it seems), and when you leave the cell, it takes the selected value from the combobox and changes back to textboxCell with the value included.
is just a simple style setting for the DataGridViewComboBoxColumn property:
yourGridColumnComboBox.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
This will make it appear like a TextBox, but when it has focus with selectable items, it will show the drop down button.

DataGridView Default Error on ComboBox Column

I have a DataGridView in my .NET 4.5 WinForms app with two columns. One column is a regular textbox column and the other column is a DataGridViewComboBoxColumn that is a dropdown. I am trying to bind the columns to a BindingList of my Filter object and I would like everything inside of the enum FilterType to show up in the dropdown. Here's the code for my object and enum:
public class Filter
{
public string keyword { get; set; }
public FilterType type { get; set; }
}
public enum FilterType : int //the strings should appear in the dropdown
{
SESSION = 1,
ORDER = 2,
SHIPMENT = 3
}
I have manually created the columns in the VS 2012 designer where I changed the ColumnType, HeaderText, and DataPropertyName to keyword and type.
Using an answer I found here I have added these two lines of code to my form loading event:
colFilterType.DataSource = Enum.GetValues(typeof(FilterType));
colFilterType.ValueType = typeof(FilterType);
When I run the code I initially see a blank row. Whenever I click on the row, irregardless of which column is clicked, I get a pop-up error.
System.ArgumentException: DataGridViewComboBoxCell value is not valid. ... please handle the DataError event.
I can ignore it and type whatever text I want into the Keyword column, and the dropdown is magically filled in with the first value of the enum. However, if I even mouse-over the dropdown the error pops up again (please see the screenshot). I am not sure what causes the error and don't know where to set a breakpoint. I also do not know if I'm creating the problem by making parts of the DataGridView in the designer and modifying those in code. The designer does not let me set the DataSource the way I did in the code. It also contains a field ValueMember that I haven't seen used in code.
Although not ideal, I wouldn't mind catching the error and doing nothing with it since the dropdown seems to populate itself (and assuming all the data stays intact).
Your code works fine when adding the column at runtime. Sample code:
DataGridViewComboBoxColumn colFilterType = new DataGridViewComboBoxColumn();
colFilterType.HeaderText = "Name you want";
colFilterType.DataSource = Enum.GetValues(typeof(FilterType));
colFilterType.ValueType = typeof(FilterType);
dataGridView1.Columns.Add(colFilterType);
Errors like the one you report are usually provoked while changing the type of a cell/column at runtime, because of the big number of events which are triggered every time a DataGridView is affected in any way: some of them expect the old type and find elements with the new one (e.g., expecting an int and finding a string).

Not able to hide first column in datagridview?

I have a datagridview in a windows form which contains some columns. And I want to hide the Ist column(CompanyID) through the code behind.
But Ist column is not hiding.
Have tried below 2 things :
dgvVendorDetails.Columns["CompanyID"].Visible = false;
And:
dgvVendorDetails.Columns[0].Visible = false;
I don't know the reason behind this. I have searched a lot but got no solution.
Both of these syntax are corrects and should work:
dgvVendorDetails.Columns["CompanyID"].Visible = false;
dgvVendorDetails.Columns[0].Visible = false;
My guess is that you are using the DataGridView.AutoGenerateColumns functionnality and even if you set the DataSource property, the DatagridView won't create columns until the grid is displayed.
So it's possible that:
you try to access columns that do not exist yet (but the code should raise an exception)
or you access valid columns, but they are replaced when the grid is bound again and so your code has no effect (probably your case since you do not mention an exception).
If so, the solution is to use the DataBindingComplete Event.
See also these related issues:
Why DataGridColumn not getting removed from DataGridView
Datagirdview and tabcontrol issue
Strange issue with a datagridview and a tabcontrol C#
DataGridView has no columns
EDIT
As #brikovich pointed out, another solution is not not use the AutoGenerated columns but create them and configure them at design time or at runtime.
This thread How to select visible columns in Datagridview bound to DataTable can help you to achieve this and/or make a choice between these two options.
Set autogenerate columns to false and then add each column one by one to the grid. Then set the column you don't want to see to visible = false. No need for code behind.
Try this:
VB.net:
Private Sub dgvVendorDetails_ColumnAdded(sender As Object, e As DataGridViewColumnEventArgs) Handles dgvVendorDetails.ColumnAdded
If e.Column.Name = "CompanyID" Then dgvVendorDetails.Columns("CompanyID").Visible = False
End Sub
C#:
private void dgvVendorDetails_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.Name == "CompanyID")
dgvVendorDetails.Columns("CompanyID").Visible = false;
}

How to end the DataGridView Cells Edit Mode automatically?

this is a follow up question from my previous one. you can find it here.
I got another problem after finally solving my previous one, when I assign the button to add the value into a new row in DataGrid, the entire cell will be on edit mode, until I clicked on other cell and filled it and/or tabbed till the end of the row (well apparently this one doesn't work), then it will end the edit mode.
I'm using dataGridView.BeginEdit(true); to begin the edit mode so that I could parse a value into the textbox (see my previous question). So, if I insert another value and press the button, the new value will replace the old value that was inserted previously because it is currently still on edit mode.
I was trying to use dataGridView.EndEdit();, dataGridView.EndEdit(DataGridViewDataErrorContexts.Commit);, cell.DataGridView.EndEdit() and cell.DataGridView.EndEdit(DataGridViewDataErrorContexts.Commit); but apparently that doesn't end the edit mode :(
What I wanted is when I press the button, the value inside the textbox will be inserted into the first textbox column (this one already worked). Then I don't have to click or fill the other column to end the edit mode. So, I'll just type anything into the textbox and press the button only until I wanted to stop. After that I begin to fill the other column.
does anyone know how to solve this?
EDIT 1: do you see the difference? look at the red circle, the top one is currently in edit mode (because it has a * after the arrow). the bottom one is not in edit mode (I did it manually by picking an item from the combobox).
Here is my code as requested from my previous question:
private void button1_Click(object sender, EventArgs e)
{
this.surat_jalanDataGridView.AllowUserToAddRows = true;
string tokNum = this.textBox1.Text;
if (this.textBox1.Text != "")
{
foreach (DataGridViewRow sjRow in this.surat_jalanDataGridView.Rows)
{
int RowIndex = surat_jalanDataGridView.RowCount - 1;
DataGridViewRow R = surat_jalanDataGridView.Rows[RowIndex];
DataTable table = new DataTable();
DataRow newRow = table.NewRow();
table.Rows.Add(newRow);
DataGridViewCell cell = R.Cells[2];
this.surat_jalanDataGridView.CurrentCell = cell;
this.surat_jalanDataGridView.BeginEdit(true);
R.Cells[2].Value = tokNum;
cell.DataGridView.EndEdit(DataGridViewDataErrorContexts.Commit);
}
}
this.surat_jalanDataGridView.EndEdit(DataGridViewDataErrorContexts.Commit);
}
EDIT 2: So, I drag and drop the surat_jalan from the data sources into my windows form. then it automatically become a datagrid with the property name surat_jalanDataGridView and the data source is surat_jalanBindingSource
Sorry about the delay. After seeing how you set up your binding to your DataGridView I can definately give you better guidance on how to edit the data that the grid is bound to. When you dragged the table from the data sources view in Visual Studio and dropped it on the DataGridView, Visual Studio did several things for you. It is important that you at least understand the basics of what was done so that you understand how you can manipulate you data moving forward. This
MSDN article how to setup binding to windows forms controls from Visual Studio. The last section describes what you are doing. The last sentences "The DataGridView control is now bound to the table that you have dragged onto it. A DataSet, TableAdapter, and BindingSource appear in the component tray." are the important ones. Since Visual Studio generated code that bound your control to your table you should edit the data directly to update your data grid view. In this case you should work with the generated DataSet (I'm assuming it was named surat_jalanDataSet). Here is a description of how to edit data in a DataSet. For your specific case Adding Rows. Please let me know if this helps you acheive your goals.
My work around to force a Cell out of EditMode is to toggle the CurrentCell.ReadOnly property.
this.dataGridView.EndEdit();
this.dataGridView.CurrentCell.ReadOnly = !dataGridView.CurrentCell.ReadOnly;
this.dataGridView.CurrentCell.ReadOnly = !dataGridView.CurrentCell.ReadOnly;
Similar technique works with other components that do not have explicit and functional EndEdit or Commit type methods.
For example, you can end the DateTimePicker's text edit mode by toggling its dateTimePicker.Enabled property.
//AJ

DataGridViewComboBox - Display 'InActive' value in DataGridView

I have a DataGridView that contains a combo box (DataGridViewComboBoxColumn). This combo box is populated with a set of setup values. These setup values can be inactivated such that only active values are displayed in the combo box, however, existing entries(records) that use the inactive values must still be displayed.
I can successfully loop over the items in the grid and if a record has a value that is no longer active (i.e. part of the DataGridViewComboBoxCell items), I simply add it to the items for that DataGridViewComboBoxCell.
Problem:
I am unable to find a place to put this code such that I do not get the dreaded 'DataGridViewComboBoxCell value is not valid.'
For example, I can put this code into the Paint event of the DataGridView and the grid functions perfectly. No issues with editing/updating values nor do I have any issues in terms of display (inactive value is always shown)... However, it still throws the 'DataGridViewComboBoxCell value is not valid.' error.
Question:
Where can I add code (or how) to add an 'inactive' value after the active values have been added to the combo box (DataGridViewComboBoxColumn), but before the records are bound to avoid getting this error?
What about just catching the datagridview error and doing nothing with it.
void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
e.Cancel = true;
}
// Add code in user interface
dataGridView1.DataError +=
new DataGridViewDataErrorEventHandler(dataGridView1_DataError);

Categories

Resources