'DataGridView AllowUserToAddRow property doesn't work
I have a simple project with Entity Framework, I have a DataGridView in my Form and I set its AllowUserToAddRow property to true but still I can not add new rows into it.
And here is my code:
DBEntities context = new DBEntities();
private void Form1_Load(object sender, EventArgs e)
{
var q = (from i in context.myTable
select i).ToList();
DataGridView.DataSource = q;
}
private void btnSave_Click(object sender, EventArgs e)
{
context.SaveChanges();
MessageBox.Show("saved successfully");
}
If I use a BindingSource control, it allow me to insert rows in DataGridView but with this approach after I call context.SaveChanges() nothing insert in my database file. So I thought maybe its relative to this problem that DataGridView with true AllowUserToAddRow property doesn't let me to insert row in DataGridView.
Solution 1:[1]
Your problem is that you call .ToList() and materialize your query - this appears to break the full databinding.
You should be able to simply have:
DBEntities context = new DBEntities();
private void Form1_Load(object sender, EventArgs e)
{
var q = (from i in context.myTable
select i);
DataGridView.DataSource = q;
}
I tried this and it works fine for allowing new rows (you do need to have a primary key in your table but you should have that anyway).
Do Note: this behaviour has been intentionally broken in Entity Framework 4.1 - Webforms data binding with EF Code-First Linq query error
I say should in my answer because I'm actually a little surprised it is this easy. I recall it not working so nicely in earlier versions of Entity Framework and I haven't used 4.0 very much.
If the solution above doesn't work you may have to do this the hard way and add new objects yourself before saving:
First introduce a binding source and when you save do something like (with an imaginary entity of Customer in the example):
foreach (Customer customer in bs.List)
{
// In my db customerId was an identity column set as primary key
if (customer.CustomerId == 0)
context.Customers.AddObject(customer);
}
context.SaveChanges();
Solution 2:[2]
I have just painfully upgraded to EF 6 from 4 and I have a similar issue, the solution in EF6 is below and I have shown a where statement for further help.
DBEntities context = new DBEntities();
private void Form1_Load(object sender, EventArgs e)
{
context.MyTable.Where(e => e.myField == 1).Load();
BindingSource bs = new BindingSource();
bs.DataSource = context.MyTable.Local.ToBindingList();
myDatagridView.DataSource = bs;
}
You can now use context.SaveChanges(); to save the changes or inserts
Solution 3:[3]
I have had a similar issue with a custom database implementation of an Interbase dialect. The solution for me was similar to that of above:
var tableAList = _dbImplementation.SelectAll<TableA>().ToList();
var bindingSource = new BindingSource();
bindingSource.DataSource = typeof (TableA);
foreach (var tableA in tableAList)
{
bindingSource.Add(tableA);
}
dataGridView.DataSource = bindingSource;
Helpful reference: A Detailed Data Binding Tutorial
Solution 4:[4]
If you are going to bind the dataGridView to a source, then the only appropriate way to insert a row is to add a row to the data structure your DataGridView is binded to.
Solution 5:[5]
For me the problem was that I had added two new DataGrids to my form that are bound through a BindingList - but forgot to make a class for them inheriting from INotifyPropertyChanged. I had something like this:
public BindingList<String> MyProperty { get; set; } = "";
But it should have been this:
public BindingList<TextAndOrder> MyProperty { get; set; } = new BindingList<TextAndOrder>();
In order for BindlingList to work it must be bound to a class that inherits from INotifyPropertyChanged
Where TextAndOrder Class was:
public class TextAndOrder : INotifyPropertyChanged { private String _text = ""; private int _order = 0; public String Text { get { return _text; } set { if (_text != value) { _text = value; this.NotifyPropertyChanged("Text"); } } } public int Order { get { return _order; } set { if (_order != value) { _order = value; this.NotifyPropertyChanged("Order"); } } } private void NotifyPropertyChanged(string propertyName) { if (PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; }
My Binding in the MainForm.cs was like:
grid.DataSource = MayDataClass.MyProperty; grid.AllowUserToAddRows = true; grid.AllowUserToDeleteRows = true; grid.AllowUserToResizeRows = true; grid.AllowUserToResizeColumns = true;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Community |
| Solution 2 | 27k1 |
| Solution 3 | |
| Solution 4 | Aman |
| Solution 5 | John Foll |
