Reputation: 1133
What is the best way to refresh a DataGridView
when you update an underlying data source?
I'm updating the datasource frequently and wanted to display the outcome to the user as it happens.
I've got something like this (and it works), but setting the DataGridView.DataSource
to null
doesn't seem like the right way.
List<ItemState> itemStates = new List<ItemState>();
dataGridView1.DataSource = itemStates;
for (int i = 0; i < 10; i++) {
itemStates.Add(new ItemState { Id = i.ToString() });
dataGridView1.DataSource = null;
dataGridView1.DataSource = itemStates;
System.Threading.Thread.Sleep(500);
}
Upvotes: 75
Views: 129041
Reputation: 1
Just delete all Rows and fill it after deleting:
BindingList<ItemState> itemStates = new BindingList<ItemState>();
datagridview1.Rows.Clear();
for(int i = 0; i < 10; i++)
{
itemStates.Add(new ItemState { id = i.ToString() });
}
datagridview1.DataSource = itemStates;
Thread.Sleep(500);
Upvotes: 0
Reputation: 14569
The cleanest, most efficient and paradigm-friendly solution in this case is to use a System.Windows.Forms.BindingSource
as a proxy between your list of items (datasource) and your DataGridView
:
var itemStates = new List<ItemState>();
var bindingSource1 = new System.Windows.Forms.BindingSource { DataSource = itemStates };
dataGridView1.DataSource = bindingSource1;
Then, when adding items, use Add()
method of BindingSource
instead of your list's Add()
method:
for (var i = 0; i < 10; i++)
{
bindingSource1.Add(new ItemState { Id = i.ToString() });
System.Threading.Thread.Sleep(500);
}
This way you adding items to your list and notifying DataGridView
about those additions with the same line of code. No need to reset DataGridView
's DataSource
every time you make a change to the list.
It also worth mentioning that you can drop a BindingSource
onto your form directly in Visual Studio's Forms Designer and attach it as a data source to your DataGridView
there as well, which saves you a line of code in the above example where I'm doing it manually.
Upvotes: 35
Reputation: 495
You are setting the datasource inside of the loop and sleeping 500 after each add. Why not just add to itemstates and then set your datasource AFTER you have added everything. If you want the thread sleep after that fine. The first block of code here is yours the second block I modified.
for (int i = 0; i < 10; i++) {
itemStates.Add(new ItemState { Id = i.ToString() });
dataGridView1.DataSource = null;
dataGridView1.DataSource = itemStates;
System.Threading.Thread.Sleep(500);
}
Change your Code As follows: this is much faster.
for (int i = 0; i < 10; i++) {
itemStates.Add(new ItemState { Id = i.ToString() });
}
dataGridView1.DataSource = typeof(List);
dataGridView1.DataSource = itemStates;
System.Threading.Thread.Sleep(500);
Upvotes: 0
Reputation: 24433
I ran into this myself. My recommendation: If you have ownership of the datasource, don't use a List. Use a BindingList. The BindingList has events that fire when items are added or changed, and the DataGridView will automatically update itself when these events are fired.
Upvotes: 60
Reputation: 3034
Observablecollection :Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. You can enumerate over any collection that implements the IEnumerable interface. However, to set up dynamic bindings so that insertions or deletions in the collection update the UI automatically, the collection must implement the INotifyCollectionChanged interface. This interface exposes the CollectionChanged event, an event that should be raised whenever the underlying collection changes.
Observablecollection<ItemState> itemStates = new Observablecollection<ItemState>();
for (int i = 0; i < 10; i++) {
itemStates.Add(new ItemState { Id = i.ToString() });
}
dataGridView1.DataSource = itemStates;
Upvotes: 4
Reputation: 1149
This is copy my answer from THIS place.
Only need to fill datagrid again like this:
this.XXXTableAdapter.Fill(this.DataSet.XXX);
If you use automaticlly connect from dataGridView this code create automaticlly in Form_Load()
Upvotes: 0
Reputation: 6689
Well, it doesn't get much better than that. Officially, you should use
dataGridView1.DataSource = typeof(List);
dataGridView1.DataSource = itemStates;
It's still a "clear/reset source" kind of solution, but I have yet to find anything else that would reliably refresh the DGV data source.
Upvotes: 51
Reputation: 90
Try this Code
List itemStates = new List();
for (int i = 0; i < 10; i++)
{
itemStates.Add(new ItemState { Id = i.ToString() });
dataGridView1.DataSource = itemStates;
dataGridView1.DataBind();
System.Threading.Thread.Sleep(500);
}
Upvotes: -5