views:

777

answers:

1

I've got a datagrid control bound to BindingList of objects. One of the Properties of the object class is boolean. I have customized that column in the datagridview to be a checkbox type.

Things work correctly when the datagridview loads for the rows that have values brought in from the binding list. However, when the "new entry" line is painted, a System.FormatException is thrown on the checkbox cell.

Exact Error message (relevant portion):

The following exception occurred in the DataGridView:

System.FormatException: Value '' cannot be converted to type 'Boolean'. at System.Windows.Forms.Formatter.FormatObjects....

My searching indicated that this can occur when the true, false, and indeterminate values of the checkbox column are not set.
URL Referencing similar problem to mine:

http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/c29427ff-18be-4fb0-a0a7-d1940e1cd817

However, I have set these values (shown in code below). Beyond this, i can't find any other information relevant to my problem. I'm fairly sure the problem is localized to the use of the checkbox, since, when i change the column type to a simple textbox, i get no exception errors, simply a column of true / false with the "new entry" line showing no value.

DataGridView code:

// 
        // dataGridView1
        // 
        this.dataGridView1.AllowUserToResizeRows = false;
        dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
        dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
        dataGridViewCellStyle1.NullValue = null;
        dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
        dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
        this.dataGridView1.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
        this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
        this.dataGridView1.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.DisplayedCells;
        this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
        this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.columnDescription,
        this.columnExpedite,
        this.columnId,
        this.columnQuantity,
        this.columnEntryDate,
        this.columnUpdateDate});
        this.dataGridView1.Location = new System.Drawing.Point(3, 5);
        this.dataGridView1.Name = "dataGridView1";
        this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
        this.dataGridView1.Size = new System.Drawing.Size(1015, 241);
        this.dataGridView1.TabIndex = 0;
        // 
        // columnDescription
        // 
        this.columnDescription.DataPropertyName = "Description";
        this.columnDescription.FillWeight = 200F;
        this.columnDescription.HeaderText = "Description";
        this.columnDescription.Name = "columnDescription";
        // 
        // columnExpedite
        // 
        this.columnExpedite.DataPropertyName = "Expedite";
        this.columnExpedite.FalseValue = "false";
        this.columnExpedite.HeaderText = "Expedited";
        this.columnExpedite.Name = "columnExpedite";
        this.columnExpedite.Resizable = System.Windows.Forms.DataGridViewTriState.True;
        this.columnExpedite.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
        this.columnExpedite.TrueValue = "true";
        this.columnExpedite.IndeterminateValue = "false";
        // 
        // columnId
        // 
        this.columnId.DataPropertyName = "Id";
        this.columnId.HeaderText = "Id";
        this.columnId.Name = "columnId";
        this.columnId.Visible = false;
        // 
        // columnQuantity
        // 
        this.columnQuantity.DataPropertyName = "Quantity";
        this.columnQuantity.HeaderText = "Quantity";
        this.columnQuantity.Name = "columnQuantity";
        // 
        // columnEntryDate
        // 
        this.columnEntryDate.DataPropertyName = "EntryDateTime";
        dataGridViewCellStyle2.Format = "g";
        dataGridViewCellStyle2.NullValue = null;
        this.columnEntryDate.DefaultCellStyle = dataGridViewCellStyle2;
        this.columnEntryDate.HeaderText = "Entry Date/Time";
        this.columnEntryDate.Name = "columnEntryDate";
        this.columnEntryDate.ReadOnly = true;
        this.columnEntryDate.Resizable = System.Windows.Forms.DataGridViewTriState.True;
        this.columnEntryDate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
        // 
        // columnUpdateDate
        // 
        this.columnUpdateDate.DataPropertyName = "UpdateDateTime";
        this.columnUpdateDate.HeaderText = "Last Update Date/Time";
        this.columnUpdateDate.Name = "columnUpdateDate";
        this.columnUpdateDate.ReadOnly = true;
        this.columnUpdateDate.Resizable = System.Windows.Forms.DataGridViewTriState.True;
        this.columnUpdateDate.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;

Edit Added: A couple additional things i've tried:

  • Attempted using the DefaultValueNeeded event. default value loads when i "touch" the new entry line, but exception fired prior to that, when "new entry" line is actually painting.

  • Attempted to use dataGridView1.Columns["columnExpedite"].DefaultCellStyle.NullValue = "false"; with same results.

How do i resolve this exception?

A: 

I may be reading this wrong, but this sounds like an order-of-operations issue. I don't see the code where you add the item to the list so I'm not 100% sure on his, but I would guess that you're adding the new object to the list and then modifying the values

You need to ensure that the boolean value is not null. If you're adding a new item,. you will need to populate the value of the object being added before you add it to he list. One possible way to ensure this is to set a default value of either false or true, or set this in the constructor.

Edit - Added

I didn't test this myself, but I'm hoping it will work for you.

Can you hook into the DefaultValuesNeeded event of the DataGridView? That event should fire before the exception is thrown, which should resolve the issue...

David Stratton
This is a good point. I should have addressed that, my bind statement occurs on form load. Further, my constructor does actually set a default value for the boolean member. WHen i click on the "new entry" line, the defaults are pulled in (i also set default dates). The problem occurs on when the "new entry" line is painted to the screen.
Allen
I tried that event, and set a value... and it does populate, but not until i click on the new entry...the exception fires when the new entry line paints. THe draw literally pauses on that cell.
Allen