Hi there,
I'm currently having a really weird problem. I have created a custom control with 2 gridviews and 2 custom scrollbars on it, gridHeader on top, gridData on the bottom. The first gridview (gridHeader) is used for the user to enter a search query on every individual column. The second gridview (gridData) is used to view the resulting data. For each column in gridHeader I also create a filter control that will be placed over the columnheader, with this filter control the user can also filter the data by checking on/off the unique values in list of the column(click on a little button in the column and you'll see the unique values).
The control works and has proven itself, BUT it's too slow. It can take up to 1000 ms to load some datasource. After checking the code by adding timers I figured out the problem is not the heavy filtering I do, it turns out its caused by the gridviews when being assigned to a datatable and also while adding the filter controls to the columnheaders.
To kinda solve the second problem I started by not removing the FilterColumnClass when not detected and leaving them in memory, so the second load will be faster. But if I assign the datasource of the header-gridview filled with only 1 row it takes about 180 ms, while when I assign the datasource of the data-gridview filled with 100 rows it only takes about 10 ms.
When the header-grid is assigned, 1 event gets triggerd which doesn't do anything because of the "_StopEventHandling" flag which is set to true.
I've put the timings as a comment in the code, 1st means; The first time you assign a datatable to the control, 2nd means; The second time you've assigned a datatable. The time in ms you see is the time it took compaired to the beginning of the function or compaired to the last time-snapshot.
Here is part of the code in question:
public class SomeCustomUserControl
{
private DataTable _AllData = null;
private DataTable _ViewData = null;
private List<FilterColumnClass> _FilterColumns = new List<FilterColumnClass>();
private bool _StopEventHandling = false;
private bool _DataBound = false;
private bool _DataBoundToSendSelected = false;
private int _LastSortColumnIndex = -1;
private bool _LastSortColumnDir = false;
public void SetDataSource(DataTable value)
{
foreach (FilterColumnClass filter in _FilterColumns)
{
filter.FilterCheckControl.Visible = false;
}
_AllData = value;
DataBind();
}
private void DataBind()
{
if (_AllData != null)
{
_DataBound = true;
_StopEventHandling = true;
PrepareGridViews();
PrepareFilterColumns();
_ViewData = FilterRows(_AllData, _FilterColumns);
gridData.DataSource = _ViewData;
if (_LastSortColumnIndex != -1)
{
if (gridHeader.Columns.Count > _LastSortColumnIndex)
{
try
{
if (_LastSortColumnDir)
gridData.Sort(gridData.Columns[gridHeader.Columns[_LastSortColumnIndex].Name], ListSortDirection.Ascending);
else
gridData.Sort(gridData.Columns[gridHeader.Columns[_LastSortColumnIndex].Name], ListSortDirection.Descending);
}
catch
{
}
}
}
if (gridData.Columns.Count > 0) Personalize_Columns();
PrepareScrollBars();
SetVerticalPosition(vScrollBar1.Value);
foreach (DataGridViewColumn col in gridHeader.Columns)
{
if (col.DisplayIndex == 0)
{
_LastScrollingColumnIndex = -1;
SetHorizontalPosition(col.Index);
}
}
AskMarkedItems();
_DataBoundToSendSelected = true;
_StopEventHandling = false;
}
else
{
gridHeader.DataSource = null;
gridData.DataSource = null;
_ViewData = null;
}
}
private void PrepareGridViews()
{
SetDoubleBuffered(gridData, true);
SetDoubleBuffered(gridHeader, true);
gridHeader.RowTemplate.Height = PublicFunctions.UniversalHeight - 6;
gridData.RowTemplate.Height = PublicFunctions.UniversalHeight - 6;
gridData.ColumnHeadersVisible = false;
}
private void PrepareFilterColumns()
{
int index = 0;
this.SuspendLayout();
foreach (DataColumn col in _AllData.Columns)
{
FilterColumnClass filter = _FilterColumns.Find(delegate(FilterColumnClass item) { return item.ColumnName == col.ColumnName; });
if (filter != null)
{
filter.Index = index;
filter.FilterCheckControl.Visible = true;
}
else
{
FilterColumnClass new_filter = new FilterColumnClass();
new_filter.ColumnName = col.ColumnName;
new_filter.Index = index;
new_filter.FilterCheckControl.Visible = true;
new_filter.FilterCheckControl.eventAskCurrentDataTable += new AskDataTableByInt(FilterCheckControl_eventAskCurrentDataTable);
new_filter.FilterCheckControl.eventAskSourceDataTable += new AskDataTableByInt(FilterCheckControl_eventAskSourceDataTable);
new_filter.FilterCheckControl.eventApplyFilter += new EventHandler(FilterCheckControl_eventApplyFilter);
_FilterColumns.Add(new_filter);
this.Controls.Add(new_filter.FilterCheckControl);
}
index++;
}
this.ResumeLayout();
foreach (FilterColumnClass filter in _FilterColumns)
{
bool found = false;
foreach (DataColumn col in _AllData.Columns)
{
if (filter.ColumnName == col.ColumnName)
{
found = true;
break;
}
}
if (!found)
{
filter.FilterCheckControl.Visible = false;
}
}
DataTable header = new DataTable("FilterRow");
foreach (DataColumn col in _AllData.Columns)
{
header.Columns.Add(new DataColumn(col.ColumnName, typeof(string)));
}
DataRow filterrow = header.NewRow();
foreach (FilterColumnClass filter in _FilterColumns)
{
if (filter.FilterCheckControl.Visible)
{
try
{
filterrow.ItemArray[filter.Index] = filter.FilterTextString;
}
catch (Exception ex)
{
PublicFunctions.ReportBug(ex, _Shared);
}
}
}
header.Rows.Add(filterrow);
gridHeader.DataSource = header;
}
private void SetDoubleBuffered(DataGridView grid, bool setting)
{
Type dgvType = grid.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(grid, setting, null);
}
}
I hope you guys can see through the big amount of code.