Reputation: 1767
I want to display a table. Data for table must to be precalculated and it is heavy calculation. Also result table is long. I want to provide acces to part of data while another part is calculated in the background.
I wrote background worker for calculation and DataGridView for display. Sometimes worker submit new rows via ProgressChangedEvent. I am tried to add this rows at bottom. My problem starts when I tried add new rows at bottom. My UI is freezes.
Here is how I initialize DataGridView:
private void InitDataGridView()
{
BindingList<TableRow> tableRows = new BindingList<TableRow>();
dataGridView.DataSource = tableRows;
}
and here is how I adding new rows at bottom in ProgressChangedEvent
private void UpdateDataGridView (List<Items> newItems)
{
BindingList<TableRow> dataSource = (BindingList<TableRow>)this.dataGridView.DataSource;
foreach (var item in newItems)
dataSource.Add(new TableRow(item));
}
I think that problem is because adding one row initiate redrawing of the table. But I don't found AddRange for BindingList or mechanism to stop rendering temporary.
Any suggestions?
Upvotes: 1
Views: 1909
Reputation: 125247
By adding a new item to the list, BindingList
raises a ListChanged
which leads to updating DataGridView
. To make updating of DataGridView
more efficient, as an option you can stop raising ListChanged
event of the BindingList
. This way you can turn it off before adding items and then turn it on and raise the event just after adding a group of items to the list.
Here is an implementation which supports turning ListChanged
event on/off:
public class MyBindingList<T>:BindingList<T>
{
public bool EnableChangeNotifications { get; set; }
protected override void OnListChanged(ListChangedEventArgs e)
{
if(EnableChangeNotifications)
base.OnListChanged(e);
}
}
And for example, disable the event when adding items::
list.EnableChangeNotifications = false;
//Add new items to the list using a loop or something else.
Then to showing changes in DataGridView
, enable the event and raise it:
list.EnableChangeNotifications = true;
list.ResetBindings();
Upvotes: 1
Reputation: 1322
Try setting the AutoSizeColumnsMode
property to None
or DisplayedCells
, as well as set on the AutoSizeMode
on each column:
foreach (DataGridViewColumn c in thisGrid.Columns)
{
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
}
Try toggling this before and after binding, and when updating.
Also, you can try what is suggested on this answer and enable double buffering:
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
Type dgvType = dataGridView1.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dataGridView1, value, null);
}
Upvotes: 0