Share via


DataGridView not displaying the add new row

Question

Wednesday, July 16, 2008 12:36 PM

Hello!

When I bind a BindingList<custom class> to a DataGridView there is no empty row with a * at the button for inserting new values. It shows up in the Visual Studio designer but disappears when i run the app. What do I have to do to show it? I have set the AllowUserToAddRows property to true. I am using a CheckBoxColumn and a ComboBoxColumn in addition to the regular TextBox columns. All the columns are created in the designer, the combobox choices are added to the Items-collection (also in the designer) and the BindingList<T> is bound to the DGVs DataSorce in code.

/Miro

All replies (5)

Wednesday, July 16, 2008 12:56 PM ✅Answered | 1 vote

For this to work without modification, the underlying type ("custom class") must have a public, parameterless constructor, so that it can create new rows. Alternatively, you can attach to the AddingNew event of the binding-list, and set the args .NewObject.

IIRC, BindingSource has a similar event, but in this case it will probably be easier to use the AddingNew event.

If your class already has a public parameterless constructor, that is odd: any chance you can post something that illustrates it?


Marc


Wednesday, July 16, 2008 7:44 PM

Thanks for your fast answer. It helped to add an constructor without parameters. Seems kind of obvious, now.

But since I need the class to have some of it's properties to be set, I wonder if there is an easy way to force a column in a datagridview to be "not nullable". If not, which event do I have to listen to, in order to prevent the user from leaving the row before all the neccessary fields are filled?

/Miro


Thursday, July 17, 2008 6:14 AM

The grid displays something akin to the object - so if you make the object's property non-nullable, the grid should be too. Alternatively you can implement IDataErrorInfo (very simple) to provide vidual feedback that some data is missing (although this doesn't prevent you from moving off the row).

For checking more aggressively, I suspect CellValidating or RowValidating are your friends, but I haven't used them much myself.


Marc


Tuesday, July 16, 2013 10:29 AM

I have the exact same problem. A List<"Custom Class"> as datasource for a DataGridView and even though the AllowUserToAddRows property is set to true, there is no way to add a new row.

Doing anything in the events you mentioned does nothing.

In the designer, the DataGridView is empty as columns and data are added during runtime with dataGridView1.DataSource = List<"Custom Class"> and during runtime only the existing elements of the list are displayed and editable.

I have bound two DataGridViews to the same List but this problem is the same with only a single DataGridView as well.

Here is my code(Form1):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private List<Block> blocks;
        public Form1()
        {
            InitializeComponent();
            dataGridView1.AllowUserToAddRows = true;
            dataGridView2.AllowUserToAddRows = true;
            dataGridView1.AllowUserToDeleteRows = true;
            dataGridView2.AllowUserToDeleteRows = true;
            
            blocks = new List<Block>();
            
            Block b1 = new Block();
            Block b2 = new Block();
            Block b3 = new Block();
            
            b1.Height = 5;
            b1.Width= 5;
            b1.Depth = 5;
            b1.Name = "Block 1";

            b2.Height = 15;
            b2.Width = 2;
            b2.Depth = 23;
            b2.Name = "Testingblock second";

            b3.Height = 1;
            b3.Width = 112;
            b3.Depth = 66;
            b3.Name = "#3 / 3";

            blocks.Add(b1);
            blocks.Add(b2);
            blocks.Add(b3);
            dataGridView1.DataSource = blocks;
            dataGridView2.DataSource = blocks;
        }

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            dataGridView1.Refresh();
            dataGridView2.Refresh();
        }
    }

    public class Block
    {
        public int Height { get; set; }
        public int Width{ get; set; }
        public int Depth { get; set; }
        public string Name { get; set; }
        public DateTime Creation { get; private set; }

        public Block()
        {
            Creation = DateTime.Now;
        }
    }

}

And the designer code:namespace WindowsFormsApplication1
{
    partial class Form1
    {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Vom Windows Form-Designer generierter Code

        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.dataGridView2 = new System.Windows.Forms.DataGridView();
            this.splitter1 = new System.Windows.Forms.Splitter();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.AllowUserToOrderColumns = true;
            this.dataGridView1.BackgroundColor = System.Drawing.SystemColors.ActiveCaption;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Left;
            this.dataGridView1.Location = new System.Drawing.Point(0, 0);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.Size = new System.Drawing.Size(455, 357);
            this.dataGridView1.TabIndex = 2;
            this.dataGridView1.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellEndEdit);
            // 
            // dataGridView2
            // 
            this.dataGridView2.AllowUserToOrderColumns = true;
            this.dataGridView2.BackgroundColor = System.Drawing.SystemColors.ControlLight;
            this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView2.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView2.Location = new System.Drawing.Point(455, 0);
            this.dataGridView2.Name = "dataGridView2";
            this.dataGridView2.Size = new System.Drawing.Size(522, 357);
            this.dataGridView2.TabIndex = 3;
            this.dataGridView2.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellEndEdit);
            // 
            // splitter1
            // 
            this.splitter1.Location = new System.Drawing.Point(455, 0);
            this.splitter1.Name = "splitter1";
            this.splitter1.Size = new System.Drawing.Size(3, 357);
            this.splitter1.TabIndex = 4;
            this.splitter1.TabStop = false;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(977, 357);
            this.Controls.Add(this.splitter1);
            this.Controls.Add(this.dataGridView2);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.DataGridView dataGridView2;
        private System.Windows.Forms.Splitter splitter1;




    }
}

Thanks.


Wednesday, April 4, 2018 6:45 PM

I see two issues with the above code from Ihsiirou, that I stumbled across while trying to debug my own situation (more on that at the very end).

First of all, you cannot expect to bind the SAME list two TWO datagridviews, and have that work in any way that is likely to be expected.

Even if it were not for that, the problem with the above lies in these two lines, because "blocks" is a List<block> instead of a BindingList<block>

dataGridView1.DataSource = blocks; dataGridView2.DataSource = blocks;

Instead try:

blocks2 = new List<block>(blocks); // Copy of the original list

BindingList<block> bindingList1 = new BindingList<block>(blocks);

BindingList<block> bindingList2 = new BindingList<block>(blocks2);

dataGridView1.DataSource = bindingList1;

dataGridView2.DataSrouce = bindingList2;

(In my own case, today, I knew about all of this, but in the last step used the list name instead of the BindingList name for the DataSource.  Compiles.  Runs.  But no way to insert a new row.)