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");

[3659 byte] By [PhilipPuffinburger] at [2007-12-16]
# 1

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"

MarkRideout at 2007-9-9 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 2

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.

PhilipPuffinburger at 2007-9-9 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 3
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"

MarkRideout at 2007-9-9 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...
# 4
Mark Rideout wrote:
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.

That was it. The database column is a NUMBER, which translates to a Decimal. Once I changed changed the type of the Id from int to Decimal the ComboBoxColumn started working with no errors. Coming from Delphi (this program was originally written in Delphi 2) I think I got used to always doing AsInteger on NUMBERs from the database.

Sorry for the trouble. Smile

PhilipPuffinburger at 2007-9-9 > top of Msdn Tech,Windows Forms,Windows Forms Data Controls and Databinding...