Hi folks,
I am completely stuck on how to bind a KeyedCollection to a DataGridView. I can get it to work for the first record but then it has unpredictable results when I add subsequent records. It ends up throwing an exception at the line of code that opened the form, be that Form.ShowDialog() or Application.Run(new Form) - when the exception is thrown, it might be an InvalidOperationException or sometimes an OutOfRangeException.
I would love to find an example of how to do this, but I have not been able to find one.
Below I have included complete example of the code that causes the problem. The following instructions will have you replicate this:
Please do the following:1. Create a new project using the Template "Empty Project"2. Add a Class called Program.cs3. open the class and delete everything in it.4. Paste the contents of the Code Snippet below5. Add references for: System.Windows.Forms System.DrawingRun the program.Click the add buttonClick OKDouble click in a Cell of the DataGridView.What am I doing wrong!?!?!?!
Begin Code
using System; using System.Windows.Forms; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; namespace Project1 { /// <summary> /// The SubForm which the user sees when he adds a record. /// </summary> public partial class frmAdd : Form { public GridViewRecord gvr { get; set; } public frmAdd() { InitializeComponent(); this.gvr = new GridViewRecord(); tbFirstname.Text = gvr.FirstName; tbSurname.Text = gvr.Surname; tbOccupation.Text = gvr.Occupation; } private void btnOK_Click(object sender, EventArgs e) { gvr.FirstName = tbFirstname.Text; gvr.Surname = tbSurname.Text; gvr.Occupation = tbOccupation.Text; this.Close(); } } /// <summary> /// the Main Form presented to the user with all the data /// </summary> public partial class frmDataGridViewDemo : Form { private RecordCollection Items; public frmDataGridViewDemo() { InitializeComponent(); this.Items = new RecordCollection(); bindingSource1.DataSource = this.Items; dataGridView1.DataSource = bindingSource1; } private void btnAdd_Click(object sender, EventArgs e) { frmAdd Add = new frmAdd(); Add.ShowDialog(); this.Items.Add(Add.gvr); } } /// <summary> /// The individual records that are displayed in the datagridview /// </summary> public class GridViewRecord { public string FirstName { get; set; } public string Surname { get; set; } public string Occupation { get; set; } public GridViewRecord() { this.FirstName = System.Guid.NewGuid().ToString(); this.Surname = System.Guid.NewGuid().ToString(); this.Occupation = System.Guid.NewGuid().ToString(); } } /// <summary> /// The Keyed Collection with the BindingSource binds too. /// </summary> public class RecordCollection : KeyedCollection<string, GridViewRecord> { public RecordCollection() : base() { } protected override string GetKeyForItem(GridViewRecord item) { return item.FirstName; } } // =================================================== // BEGIN WINDOWS Designer Code // Everything below this line was built by the Windows // designer IDE Conglobulator. static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new frmDataGridViewDemo()); } } partial class frmAdd { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.tbFirstname = new System.Windows.Forms.TextBox(); this.tbSurname = new System.Windows.Forms.TextBox(); this.tbOccupation = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label3 = new System.Windows.Forms.Label(); this.btnOK = new System.Windows.Forms.Button(); this.SuspendLayout(); // // tbFirstname // this.tbFirstname.Location = new System.Drawing.Point(79, 23); this.tbFirstname.Name = "tbFirstname"; this.tbFirstname.Size = new System.Drawing.Size(184, 20); this.tbFirstname.TabIndex = 0; // // tbSurname // this.tbSurname.Location = new System.Drawing.Point(79, 49); this.tbSurname.Name = "tbSurname"; this.tbSurname.Size = new System.Drawing.Size(184, 20); this.tbSurname.TabIndex = 1; // // tbOccupation // this.tbOccupation.Location = new System.Drawing.Point(79, 75); this.tbOccupation.Name = "tbOccupation"; this.tbOccupation.Size = new System.Drawing.Size(184, 20); this.tbOccupation.TabIndex = 2; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(16, 26); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(55, 13); this.label1.TabIndex = 3; this.label1.Text = "First name"; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(16, 52); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(49, 13); this.label2.TabIndex = 4; this.label2.Text = "Surname"; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(16, 78); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(62, 13); this.label3.TabIndex = 5; this.label3.Text = "Occupation"; // // btnOK // this.btnOK.Location = new System.Drawing.Point(165, 101); this.btnOK.Name = "btnOK"; this.btnOK.Size = new System.Drawing.Size(98, 28); this.btnOK.TabIndex = 6; this.btnOK.Text = "OK"; this.btnOK.UseVisualStyleBackColor = true; this.btnOK.Click += new System.EventHandler(this.btnOK_Click); // // frmAddForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(284, 141); this.Controls.Add(this.btnOK); this.Controls.Add(this.label3); this.Controls.Add(this.label2); this.Controls.Add(this.label1); this.Controls.Add(this.tbOccupation); this.Controls.Add(this.tbSurname); this.Controls.Add(this.tbFirstname); this.Name = "frmAddForm"; this.Text = "Add Record"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TextBox tbFirstname; private System.Windows.Forms.TextBox tbSurname; private System.Windows.Forms.TextBox tbOccupation; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Button btnOK; } partial class frmDataGridViewDemo { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.dataGridView1 = new System.Windows.Forms.DataGridView(); this.btnAdd = new System.Windows.Forms.Button(); this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).BeginInit(); this.SuspendLayout(); // // dataGridView1 // this.dataGridView1.AllowUserToOrderColumns = true; this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView1.Location = new System.Drawing.Point(15, 17); this.dataGridView1.Name = "dataGridView1"; this.dataGridView1.Size = new System.Drawing.Size(488, 202); this.dataGridView1.TabIndex = 0; // // btnAdd // this.btnAdd.Location = new System.Drawing.Point(423, 224); this.btnAdd.Name = "btnAdd"; this.btnAdd.Size = new System.Drawing.Size(80, 28); this.btnAdd.TabIndex = 1; this.btnAdd.Text = "Add"; this.btnAdd.UseVisualStyleBackColor = true; this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); // // frmDataGridViewDemo // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(522, 264); this.Controls.Add(this.btnAdd); this.Controls.Add(this.dataGridView1); this.Name = "frmDataGridViewDemo"; this.Text = "DataGridView Demo"; ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).EndInit(); this.ResumeLayout(false); } #endregion private System.Windows.Forms.DataGridView dataGridView1; private System.Windows.Forms.Button btnAdd; private System.Windows.Forms.BindingSource bindingSource1; } }