Updating the underlying bound data for a DataGridView results in poor performance?

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Im writing a WinForms app that contains a simple object like this: public class MyObject : INotifyPropertyChanged // for two-way data binding
{
public event PropertyChangedEventHandler PropertyChanged;

private void RaisePropertyChanged([CallerMemberName] string caller = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}

private int _IndexValue;
public int IndexValue
{
get { return Value; }
set
{
if (value != Value)
{
Value = value;
RaisePropertyChanged();
}
}
}

private string _StringValue;
public string StringValue
{
get { return _StringValue; }
set
{
if (value != _StringValue)
{
_StringValue = value;
_Modified = true;
RaisePropertyChanged();
}
}
}

private bool _Modified;
public bool Modified
{
get { return _Modified; }
set
{
if (value != _Modified)
{
_Modified = value;
RaisePropertyChanged();
}
}
}

public MyObject(int indexValue)
{
IndexValue = indexValue;
StringValue = string.Empty;
Modified = false;
}
}
I have a BindingList that will contain a fixed number (100,000) of my objects as well as a BindingSource (although Im not certain if I actually need it). Both of those are defined like this:BindingList<MyObject> myListOfObjects = new BindingList<MyObject>();
BindingSource bindingSourceForObjects = new BindingSource();
bindingSourceForObjects .DataSource = myListOfObjects;
Finally, I have my DataGridView control. It has single column ("STRINGVALUECOLUMN") which displays the StringValue property for my objects and it is bound to the BindingSource that I just mentioned:dataGridViewMyObjects.DataSource = bindingSourceForObjects;
When my application starts, I add 100,000 objects to myListOfObjects. Since I only have one column in my DGV and the property that it displays is initialized to string.Empty, I basically have a DGV that contains 100,000 "blank" rows. At this point, my user can begin editing the rows to enter strings. They dont have to edit them in any order so they might put one string in the first row, the next string in row 17, the next string in row 17295, etc. Sometimes, my users will want to import strings from text file. Since I have a fixed number of objects (100,000) and there may or may not be some existing strings already entered, I have a few checks to perform during the import process before I add a new string. In the code below, Ive removed those checks but they dont seem to impact the performance of my application. However, if I import tens of thousands of strings using the code below, its very slow (like 4 or 5 minutes to import 50k lines). I have narrowed it down to something in this block of code:if (stringFromFile != string.Empty) // skip any empty lines that might be in the file
{
// do we already have an object with this string value?
MyObject myObj = myListOfObjects.Where(c => c.StringValue.Equals(stringFromFile)).FirstOrDefault();
if (myObj != null)
{
Debug.WriteLine("MyObject with index [" + myObj.IndexValue.ToString() + "] already contains this string value!");
}
else // string is not already assigned to an object
{
// find the first object whose StringValue property is empty
MyObject emptyObject = myListOfObjects.Where(c => c.StringValue.Equals(string.Empty)).FirstOrDefault();

// update the .StringValue property with the string value read from the file
emptyObject.StringValue = stringFromFile;
}
}
Im not sure if this is relevant or not but I do also have a CellFormatting event handler for my DGV so that when the databound object has its .Modified property set to true, I can ensure that the backcolor of the row has been set. if (((MyObject)dataGridViewMyObjects.Rows[e.RowIndex].DataBoundItem).Modified)
{
dataGridViewMyObjects.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Yellow;
}
else
{
dataGridViewMyObjects.Rows[e.RowIndex].DefaultCellStyle.BackColor = SystemColors.Window;
}


Im not terribly familiar with the DataGridView control so Im not sure what could be causing such bad performance but Im wondering about a few things:
1. Its my understanding that I need two-way binding so I can update the underlying data and have it reflect in the DGV control but Ive also read that INotifyPropertyChanged can be slow sometimes. Is it possible that thats causing the problem?
2. Im not a new developer but I am somewhat new to WinForms so its possible that Im just ignorant of how BindingLists, BindingSources and DGVs are supposed to work. Is there something inherently wrong with the code Ive posted?
Thanks very much for taking the time to read this!

View the full article
 
Back
Top