DataGridView and ComboBoxColumn problem
Hello
I've been trying to use a DataGridViewComboBoxColumn in a DataGridView for a couple days now. No matter what I do I get an error when the grid is being populated saying that the value is invalid. On the database (Oracle) there is a field called BlocksRule that is number based and has a Check constraint to only allow a 0 or a 1. These two values correspond text values of "All Locations" and "This Location". As an aside, if I just make the column a DataGridViewTextBoxColumn (and thereby only displaying a 0 or 1), everything works fine (all the other columns are either TextBox or CheckBox type columns).
Here's what I have so far:
A small structure that I will create an array of to use as the column's DataSource
| |
struct BlockRule { privateint mnId; privatestring msDisplay; public BlockRule(int nId,string sDisplay) { mnId = nId; msDisplay = sDisplay; } publicint Id { get {return mnId; } }publicstring Display { get {return msDisplay; } } };
|
This gets populated like this:
| |
private BlockRule[] mxBlockRules =new BlockRule[] { new BlockRule(0, "All Locations"), new BlockRule(1, "This Location")};
|
Here is the DataGridViewComboBoxColumn code:
| |
DataGridViewComboBoxColumn x_blocksRuleComboBox =new DataGridViewComboBoxColumn(); x_blocksRuleComboBox.DataSource = mxBlockRules x_blocksRuleComboBox.ValueMember = "Id"; x_blocksRuleComboBox.DisplayMember = "Display"; x_blocksRuleComboBox.DataPropertyName = "BlocksRule"; mxDataGrid.Columns.Insert(1, x_blocksRuleComboBox);
|
I also have a ComboBox on the form that displays the same thing (users want to be able to use either the grid or separated data entry controls when doing their work). The ComboBox works fine and as I move from row to row it changes to the correct values. Here is it's code (although for some reason I can not bind to the SelectedValue property - have to bind to SelectedIndex) :
| |
mxBlocksRulesComboBox.DataSource = mxBlockRules; mxBlocksRulesComboBox.DisplayMember = "Display"; mxBlocksRulesComboBox.ValueMember = "Id"; mxBlocksRulesComboBox.DataBindings.Add("SelectedIndex",this.BindingSource, "BlocksRule");
|
Philip - I tried a simple repro of this (see below) and didn't have any problems so lets dig into your scenario a bit more. Do you see this problem when clicking into a specific row or editing a specific value or when the form initially comes up?
Here is the code I tried:
| |
private BlockRule[] mxBlockRules = new BlockRule[] { new BlockRule(0, "All Locations"), new BlockRule(1, "This Location")}; public Form1() { InitializeComponent(); DataTable dt = new DataTable(); dt.Columns.Add("test", typeof(string)); dt.Columns.Add("BlocksRule", typeof(int)); dt.Rows.Add(new object[] {"zero", 0 }); dt.Rows.Add(new object[] {"one", 1}); dataGridView1.AutoGenerateColumns = false; dataGridView1.DataSource = dt; DataGridViewTextBoxColumn tc = new DataGridViewTextBoxColumn(); tc.DataPropertyName = "test"; dataGridView1.Columns.Add(tc); DataGridViewComboBoxColumn x_blocksRuleComboBox = new DataGridViewComboBoxColumn(); x_blocksRuleComboBox.DataSource = mxBlockRules; x_blocksRuleComboBox.ValueMember = "Id"; x_blocksRuleComboBox.DisplayMember = "Display"; x_blocksRuleComboBox.DataPropertyName = "BlocksRule"; dataGridView1.Columns.Add(x_blocksRuleComboBox); } } struct BlockRule { private int mnId; private string msDisplay; public BlockRule(int nId, string sDisplay) { mnId = nId; msDisplay = sDisplay; } public int Id { get { return mnId; } } public string Display { get { return msDisplay; } } }; |
(note - the above code is inside the Form1 class definition)
-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"
I tried the code you posted and it works for me, also. I see the problem when the form initially comes up. As the grid is filling up everytime it comes to the DrawGridViewComboBoxColumn, I get the "System.FormatException: DataGridViewComboBoxColumn value is not valid" error message (with a message stating to handle the DataError event if I want to replace the error box).
I don't know if this will help or not, but here is the code that immediately preceeds my above code. It's part of a method that gets called on the FormLoad event and shows the datagrid binding.
| |
mxDataSet = mxDataModule.qxGetConfig(); this.BindingSource.DataSource = mxDataSet; this.BindingSource.DataMember = mxDataSet.Tables["Config"].TableName; mxDataGrid.AutoGenerateColumns = false; mxDataGrid.DataSource = this.BindingSource;
|
mxDataModule is a utility class which in this case qxGetConfig gets called and goes out and fills a DataSet and returns it (SELECT * FROM Config).
Thanks for your help.
You mentioned that this data is coming from an Oracle database -- is there a chance that there is a type mismatch? Maybe the BlocksRule field is not Int32 based but Int64? Investigate the types and let me know.
-mark
DataGridView Program Manager
Microsoft
This post is provided "as-is"