如何排序的DataGridView数据时,虚拟模式启用 [英] How to sort DataGridView data when virtual mode Enable

查看:281
本文介绍了如何排序的DataGridView数据时,虚拟模式启用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经完成了我的虚拟数据加载的DataGridView代码,它是工作,但我想排序也应该工作时,我会点击列标题栏。我从这个线程读取想法 http://stackoverflow.com/questions/17087074/c-sharp-datagridview-virtual-mode-enable-sorting



但还是没能达到如何启用当启用DataGridView的虚拟排序模式。



我在这里发布完整的代码,也为道歉发布我的大码。所以请有人纠正我的代码或者给我小的代码部分,它帮助我网格数据虚拟数据加载一起进行排序。排序标志符号应该来过,当列标题被点击。



这里是完整的代码



 公共部分Form1类:表格
{
私人字符串的connectionString =
初始目录= Test1的;数据源= BBATRIDIP\\SQLSERVER2008R2; +
集成安全性= SSPI;坚持安全信息=假;
私人字符串表=订单;

私人缓存的MemoryCache = NULL;

公共Form1中()
{
的InitializeComponent();
this.dataGridView1.VirtualMode = TRUE;
this.dataGridView1.ReadOnly = TRUE;
this.dataGridView1.SelectionMode =
DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.CellValueNeeded + =新DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);

}

私人无效dataGridView1_CellValueNeeded(对象发件人,DataGridViewCellValueEventArgs E)
{
e.Value = memoryCache.RetrieveElement(e.RowIndex,E。参数:columnIndex);
}

私人无效btnLoad_Click(对象发件人,EventArgs五)
{

{
DataRetriever猎犬=新DataRetriever(的connectionString,表中,订单ID);
的MemoryCache =新的高速缓存(猎犬,16);
的foreach(在retriever.Columns的DataColumn列)
{
dataGridView1.Columns.Add(column.ColumnName,column.ColumnName);
}
this.dataGridView1.RowCount = retriever.RowCount;
}
赶上(异常前)
{
MessageBox.Show(连接不能建立+验证连接字符串是有效的。);
Application.Exit();
}

//调整的基础上显示的值的列宽。
this.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);

}

私人无效dataGridView1_RowPostPaint(对象发件人,DataGridViewRowPostPaintEventArgs E)
{
//这个程序会添加行无权HeaderCell随附最左边
VAR电网=发件人为DataGridView的;
变种rowIdx =(e.RowIndex + 1)的ToString();

变种centerFormat =新的StringFormat()
{
//右对齐实际上可能使对数字
对齐= StringAlignment.Center,
LineAlignment更有意义= StringAlignment.Center
};

变种headerBounds =新的Rectangle(e.RowBounds.Left,e.RowBounds.Top,grid.RowHeadersWidth,e.RowBounds.Height);
e.Graphics.DrawString(rowIdx,this.Font,SystemBrushes.ControlText,headerBounds,centerFormat);
}

私人无效dataGridView1_ColumnHeaderMouseClick(对象发件人,DataGridViewCellMouseEventArgs E)
{
//this.ValidateChildren();//力值设置为基础列表。

串strSortCol = this.dataGridView1.Columns [e.ColumnIndex] .Name点;
串strSortOrder =;

如果(this.dataGridView1.Columns [e.ColumnIndex] .HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Ascending)
{
this.dataGridView1.Columns [e.ColumnIndex] .HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Descending;
strSortOrder =ASC;
}
,否则如果(this.dataGridView1.Columns [e.ColumnIndex] .HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Descending)
{
this.dataGridView1 .Columns [e.ColumnIndex] .HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Ascending;
strSortOrder =DESC;
}

DataRetriever猎犬=新DataRetriever(的connectionString,表,strSortCol);
//dataGridView1.Refresh();
}


}


公共接口IDataPageRetriever
{
的DataTable SupplyPageOfData(INT lowerPageBoundary,诠释rowsPerPage );
}

公共类DataRetriever:IDataPageRetriever
{
私人字符串tableName值;
私人的SqlCommand命令;
私人字符串sortColumn;

公共DataRetriever(字符串的connectionString,串tableName值,串sortColumn)
{
SqlConnection的连接=新的SqlConnection(的connectionString);
connection.Open();
命令= connection.CreateCommand();
this.tableName = tableName值;
this.sortColumn = sortColumn;
}

私人INT rowCountValue = -1;如果已经确定

公众诠释行数
{
得到
{
//返回现有的值。
如果(rowCountValue!= -1)
{
返回rowCountValue;
}

//从数据库中检索的行数。
command.CommandText =SELECT COUNT(*)FROM+ tableName值;
rowCountValue =(INT)command.ExecuteScalar();
返回rowCountValue;
}
}

私人DataColumnCollection columnsValue;

公共DataColumnCollection列
{
得到
{
如果已经确定//返回现有的值。
如果(columnsValue!= NULL)
{
返回columnsValue;
}

//从数据库中检索的列信息。
command.CommandText =SELECT * FROM+ tableName值;
SqlDataAdapter的适配器=新的SqlDataAdapter();
adapter.SelectCommand =命令;
DataTable的表=新的DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.FillSchema(表,SchemaType.Source);
columnsValue = table.Columns;
返回columnsValue;
}
}

私人字符串commaSeparatedListOfColumnNamesValue = NULL;

私人字符串CommaSeparatedListOfColumnNames
{
得到
{
如果已经确定//返回现有的值。
如果(commaSeparatedListOfColumnNamesValue!= NULL)
{
返回commaSeparatedListOfColumnNamesValue;
}

//存储列名的列表在
// SupplyPageOfData方法中使用。
System.Text.StringBuilder commaSeparatedColumnNames =
新System.Text.StringBuilder();
布尔firstColumn = TRUE;
的foreach(在列的DataColumn列)
{
如果
{
commaSeparatedColumnNames.Append()(firstColumn!);
}
commaSeparatedColumnNames.Append(column.ColumnName);
firstColumn = FALSE;
}

commaSeparatedListOfColumnNamesValue =
commaSeparatedColumnNames.ToString();
返回commaSeparatedListOfColumnNamesValue;
}
}

//声明变量由SupplyPageOfData方法中重复使用。
私人字符串columnToSortBy;
私人SqlDataAdapter的适配器=新的SqlDataAdapter();

公众的DataTable SupplyPageOfData(INT lowerPageBoundary,诠释rowsPerPage)
{
//存放ID列的名称。此列必须包含唯一
//值,所以下面的SQL将正常工作。
如果(columnToSortBy == NULL)
{
columnToSortBy = this.Columns [0] .ColumnName;
}

如果(!this.Columns [columnToSortBy] .Unique)
{
抛出新的InvalidOperationException异常(的String.Format(
列{0 }必须包含唯一的值,columnToSortBy))。
}

//从数据库中检索指定的行数,从
//由lowerPageBoundary参数指定的行。
command.CommandText =选择评出的+ rowsPerPage ++
CommaSeparatedListOfColumnNames +由+ tableName值+
表示+ columnToSortBy +NOT IN(SELECT TOP+
lowerPageBoundary ++ columnToSortBy +从+
tableName值+ORDER BY+ sortColumn +
)ORDER BY+ sortColumn;
adapter.SelectCommand =命令;

DataTable的表=新的DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.Fill(表);
返回表;
}

}


公共类缓存
{
私有静态诠释RowsPerPage;

//数据表示的一页。
公共结构数据页
{
公众的DataTable表;
私人诠释lowestIndexValue;
私人诠释highestIndexValue;

公共数据页(DataTable的表,诠释的rowIndex)
{
this.table =表;
lowestIndexValue = MapToLowerBoundary(rowIndex位置);
highestIndexValue = MapToUpperBoundary(rowIndex位置);
System.Diagnostics.Debug.Assert(lowestIndexValue> = 0);
System.Diagnostics.Debug.Assert(highestIndexValue> = 0);
}

公众诠释LowestIndex
{
得到
{
返回lowestIndexValue;
}
}

公众诠释HighestIndex
{
得到
{
返回highestIndexValue;
}
}

公共静态INT MapToLowerBoundary(INT的rowIndex)
{
//返回包含给定的索引页的最低指标。
回报率(rowIndex位置/ RowsPerPage)* RowsPerPage;
}

私有静态诠释MapToUpperBoundary(INT的rowIndex)
{
//返回包含给定的索引页面的最高指标。
返回MapToLowerBoundary(rowIndex位置)+ RowsPerPage - 1;
}
}

私人数据页[] cachePages;
私人IDataPageRetriever dataSupply;

公共缓存(IDataPageRetriever dataSupplier,诠释rowsPerPage)
{
dataSupply = dataSupplier;
Cache.RowsPerPage = rowsPerPage;
LoadFirstTwoPages();
}

//如果该值是在高速缓存设置元件参数的值。
私人布尔IfPageCached_ThenSetElement(INT的rowIndex,
INT参数:columnIndex,楼盘串元素)
{
如果(IsRowCachedInPage(0和rowIndex))
{
元素= cachePages [0]。表
.Rows [rowIndex位置%RowsPerPage] [参数:columnIndex]的ToString();
返回真;
}
,否则如果(IsRowCachedInPage(1和rowIndex))
{
元素= cachePages [1]。表
.Rows [rowIndex位置%RowsPerPage] [参数:columnIndex]的ToString();
返回真;
}

返回FALSE;
}

公共字符串RetrieveElement(INT的rowIndex,INT参数:columnIndex)
{
串元素= NULL;

如果(IfPageCached_ThenSetElement(rowIndex位置,参数:columnIndex,ref元素))
{
返回元素;
}
,否则
{
返回RetrieveData_CacheIt_ThenReturnElement(
的rowIndex,参数:columnIndex);
}
}

私人无效LoadFirstTwoPages()
{
cachePages =新的数据页[] {
新的数据页(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(0),RowsPerPage),0),
新数据页(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(RowsPerPage)
RowsPerPage),RowsPerPage)};
}

私人字符串RetrieveData_CacheIt_ThenReturnElement(
INT的rowIndex,诠释参数:columnIndex)
{
//检索包含所请求的值数据的页面的价值。
DataTable的表= dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(rowIndex位置),RowsPerPage);

//从请求的细胞
//包含新检索数据的新页面替换缓存页面最远。
cachePages [GetIndexToUnusedPage(rowIndex位置)] =新的数据页(表和rowIndex);

返回RetrieveElement(rowIndex位置,参数:columnIndex);
}

//返回缓存页面的索引最远从给定的指标
//,因此最有可能被重用。
私人诠释GetIndexToUnusedPage(INT的rowIndex)
{
如果(rowIndex位置> cachePages [0] .HighestIndex&放大器;&安培;
的rowIndex> cachePages [1] .HighestIndex)
{
INT offsetFromPage0 =的rowIndex - cachePages [0] .HighestIndex;
INT offsetFromPage1 =的rowIndex - cachePages [1] .HighestIndex;
如果(offsetFromPage0< offsetFromPage1)
{
返回1;
}
返回0;
}
,否则
{
INT offsetFromPage0 = cachePages [0] .LowestIndex - rowIndex位置;
INT offsetFromPage1 = cachePages [1] .LowestIndex - rowIndex位置;
如果(offsetFromPage0< offsetFromPage1)
{
返回1;
}
返回0;
}

}

//返回指示给定的行索引是否包含
//在给定的数据页的值。
私人布尔IsRowCachedInPage(INT PAGENUMBER,诠释的rowIndex)
{
返回的rowIndex< = cachePages [PAGENUMBER] .HighestIndex&放大器;&安培;
的rowIndex> = cachePages [PAGENUMBER] .LowestIndex;
}

}


解决方案

在这里我要去职位相同的工作或多或少相同的代码,但在方法上的差异位。完整的代码如下:

 使用系统; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Data这;
使用System.Data.SqlClient的;
使用System.Drawing中;
使用System.Linq的;
使用System.Text;使用System.Windows.Forms的
;
使用的System.Reflection;
命名空间DGVirtualScroll
{
公共部分Form1类:表格
{
私人字符串的connectionString =
初始目录= Test1的;数据源= BBATRIDIP\ \SQLSERVER2008R2; +
集成安全性= SSPI;坚持安全信息=假;
私人字符串表=订单;
私人字符串strSortCol =订单ID;
私人字符串strSortOrder =ASC;

私人缓存的MemoryCache = NULL;

公共Form1中()
{
的InitializeComponent();

typeof运算(DataGridView中).InvokeMember(DoubleBuffered,
BindingFlags.NonPublic可| BindingFlags.Instance | BindingFlags.SetProperty,
空,
this.dataGridView1,
新的对象[] {真});

this.dataGridView1.VirtualMode = TRUE;
this.dataGridView1.ReadOnly = TRUE;
this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.CellValueNeeded + =新DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
}

私人无效dataGridView1_CellValueNeeded(对象发件人,DataGridViewCellValueEventArgs E)
{
e.Value = memoryCache.RetrieveElement(e.RowIndex,e.ColumnIndex);
}

私人无效btnLoad_Click(对象发件人,EventArgs五)
{
Resetsort();
LoadData(strSortCol,strSortOrder);
}

私人无效Resetsort()
{
strSortCol =订单ID;
strSortOrder =ASC;
}

私人无效LoadData(字符串strSortCol,串strSortOrder)
{

dataGridView1.Rows.Clear();
dataGridView1.Refresh();
dataGridView1.Columns.Clear();
dataGridView1.DataSource = NULL;


{
DataRetriever猎犬=新DataRetriever(的connectionString,桌子,strSortCol,strSortOrder);
的MemoryCache =新的高速缓存(猎犬,16);
的foreach(在retriever.Columns的DataColumn列)
{
dataGridView1.Columns.Add(column.ColumnName,column.ColumnName);
}
this.dataGridView1.RowCount = retriever.RowCount;
}
赶上(异常前)
{
MessageBox.Show(连接不能建立+验证连接字符串是有效的。);
Application.Exit();
}

//调整的基础上显示的值的列宽。
this.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
如果(strSortOrder ==ASC)
this.dataGridView1.Columns [strSortCol] .HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Ascending;
,否则
this.dataGridView1.Columns [strSortCol] .HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Descending;

}

私人无效dataGridView1_RowPostPaint(对象发件人,DataGridViewRowPostPaintEventArgs E)
{
//这个程序会添加行无权HeaderCell随附最左边
VAR电网=发件人为DataGridView的;
变种rowIdx =(e.RowIndex + 1)的ToString();

变种centerFormat =新的StringFormat()
{
//右对齐实际上可能使对数字
对齐= StringAlignment.Center,
LineAlignment更有意义= StringAlignment.Center
};

变种headerBounds =新的Rectangle(e.RowBounds.Left,e.RowBounds.Top,grid.RowHeadersWidth,e.RowBounds.Height);
e.Graphics.DrawString(rowIdx,this.Font,SystemBrushes.ControlText,headerBounds,centerFormat);
}

私人无效dataGridView1_ColumnHeaderMouseClick(对象发件人,DataGridViewCellMouseEventArgs E)
{
如果(strSortCol.Trim()。ToUpper的()!= this.dataGridView1.Columns [e.ColumnIndex] .Name.Trim()ToUpper的())
{
strSortOrder =ASC;
}
,否则
{
strSortOrder =(this.dataGridView1.Columns [e.ColumnIndex] .HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Ascending?DESC :ASC);
}
strSortCol = this.dataGridView1.Columns [e.ColumnIndex] .Name点;
LoadData(strSortCol,strSortOrder);
}

无效RefreshGrid()
{
//dataGridView1.Rows.Clear();
//dataGridView1.Refresh();
//dataGridView1.Columns.Clear();
//dataGridView1.DataSource = NULL;
// LoadData(strSortCol,strSortOrder);
}

}
}



*************** ***
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Data这;
使用System.Data.SqlClient的;

命名空间DGVirtualScroll
{
公共接口IDataPageRetriever
{
的DataTable SupplyPageOfData(INT lowerPageBoundary,诠释rowsPerPage);
}

公共类DataRetriever:IDataPageRetriever
{
私人字符串tableName值;
私人的SqlCommand命令;
私人字符串sortColumn;
私人串排序顺序;

公共DataRetriever(字符串的connectionString,串tableName值,字符串sortColumn,串排序顺序)
{
SqlConnection的连接=新的SqlConnection(的connectionString);
connection.Open();
命令= connection.CreateCommand();
this.tableName = tableName值;
this.sortColumn = sortColumn;
this.Sortorder =(?Sortorder.Trim()==ASC:Sortorder.Trim());
}

私人INT rowCountValue = -1;如果已经确定

公众诠释行数
{
得到
{
//返回现有的值。
如果(rowCountValue!= -1)
{
返回rowCountValue;
}

//从数据库中检索的行数。
command.CommandText =SELECT COUNT(*)FROM+ tableName值;
rowCountValue =(INT)command.ExecuteScalar();
返回rowCountValue;
}
}

私人DataColumnCollection columnsValue;

公共DataColumnCollection列
{
得到
{
如果已经确定//返回现有的值。
如果(columnsValue!= NULL)
{
返回columnsValue;
}

//从数据库中检索的列信息。
command.CommandText =SELECT * FROM+ tableName值;
SqlDataAdapter的适配器=新的SqlDataAdapter();
adapter.SelectCommand =命令;
DataTable的表=新的DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.FillSchema(表,SchemaType.Source);
columnsValue = table.Columns;
返回columnsValue;
}
}

私人字符串commaSeparatedListOfColumnNamesValue = NULL;

私人字符串CommaSeparatedListOfColumnNames
{
得到
{
如果已经确定//返回现有的值。
如果(commaSeparatedListOfColumnNamesValue!= NULL)
{
返回commaSeparatedListOfColumnNamesValue;
}

//存储列名的列表在
// SupplyPageOfData方法中使用。
System.Text.StringBuilder commaSeparatedColumnNames =
新System.Text.StringBuilder();
布尔firstColumn = TRUE;
的foreach(在列的DataColumn列)
{
如果
{
commaSeparatedColumnNames.Append()(firstColumn!);
}
commaSeparatedColumnNames.Append(column.ColumnName);
firstColumn = FALSE;
}

commaSeparatedListOfColumnNamesValue =
commaSeparatedColumnNames.ToString();
返回commaSeparatedListOfColumnNamesValue;
}
}

//声明变量由SupplyPageOfData方法中重复使用。
私人字符串columnToSortBy;
私人SqlDataAdapter的适配器=新的SqlDataAdapter();

公众的DataTable SupplyPageOfData(INT lowerPageBoundary,诠释rowsPerPage)
{
//存放ID列的名称。此列必须包含唯一
//值,所以下面的SQL将正常工作。
如果(columnToSortBy == NULL)
{
columnToSortBy = this.Columns [0] .ColumnName;
}

如果(!this.Columns [columnToSortBy] .Unique)
{
抛出新的InvalidOperationException异常(的String.Format(
列{0 }必须包含唯一的值,columnToSortBy))。
}

//从数据库中检索指定的行数,从
//由lowerPageBoundary参数指定的行。
command.CommandText =选择评出的+ rowsPerPage ++
CommaSeparatedListOfColumnNames +由+ tableName值+
表示+ columnToSortBy +NOT IN(SELECT TOP+
lowerPageBoundary ++ columnToSortBy +从+
tableName值+ORDER BY+ sortColumn ++排序顺序+
)ORDER BY+ sortColumn ++排序顺序;
adapter.SelectCommand =命令;

DataTable的表=新的DataTable();
table.Locale = System.Globalization.CultureInfo.InvariantCulture;
adapter.Fill(表);
返回表;
}

}
}

*****************
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Data这;
使用System.Data.SqlClient的;

命名空间DGVirtualScroll
{
公共类缓存
{
私有静态诠释RowsPerPage;

//数据表示的一页。
公共结构数据页
{
公众的DataTable表;
私人诠释lowestIndexValue;
私人诠释highestIndexValue;

公共数据页(DataTable的表,诠释的rowIndex)
{
this.table =表;
lowestIndexValue = MapToLowerBoundary(rowIndex位置);
highestIndexValue = MapToUpperBoundary(rowIndex位置);
System.Diagnostics.Debug.Assert(lowestIndexValue> = 0);
System.Diagnostics.Debug.Assert(highestIndexValue> = 0);
}

公众诠释LowestIndex
{
得到
{
返回lowestIndexValue;
}
}

公众诠释HighestIndex
{
得到
{
返回highestIndexValue;
}
}

公共静态INT MapToLowerBoundary(INT的rowIndex)
{
//返回包含给定的索引页的最低指标。
回报率(rowIndex位置/ RowsPerPage)* RowsPerPage;
}

私有静态诠释MapToUpperBoundary(INT的rowIndex)
{
//返回包含给定的索引页面的最高指标。
返回MapToLowerBoundary(rowIndex位置)+ RowsPerPage - 1;
}
}

私人数据页[] cachePages;
私人IDataPageRetriever dataSupply;

公共缓存(IDataPageRetriever dataSupplier,诠释rowsPerPage)
{
dataSupply = dataSupplier;
Cache.RowsPerPage = rowsPerPage;
LoadFirstTwoPages();
}

//如果该值是在高速缓存设置元件参数的值。
私人布尔IfPageCached_ThenSetElement(INT的rowIndex,
INT参数:columnIndex,楼盘串元素)
{
如果(IsRowCachedInPage(0和rowIndex))
{
元素= cachePages [0]。表
.Rows [rowIndex位置%RowsPerPage] [参数:columnIndex]的ToString();
返回真;
}
,否则如果(IsRowCachedInPage(1和rowIndex))
{
元素= cachePages [1]。表
.Rows [rowIndex位置%RowsPerPage] [参数:columnIndex]的ToString();
返回真;
}

返回FALSE;
}

公共字符串RetrieveElement(INT的rowIndex,INT参数:columnIndex)
{
串元素= NULL;

如果(IfPageCached_ThenSetElement(rowIndex位置,参数:columnIndex,ref元素))
{
返回元素;
}
,否则
{
返回RetrieveData_CacheIt_ThenReturnElement(
的rowIndex,参数:columnIndex);
}
}

私人无效LoadFirstTwoPages()
{
cachePages =新的数据页[]
{
新的数据页( dataSupply.SupplyPageOfData(DataPage.MapToLowerBoundary(0),RowsPerPage),0),
新数据页(dataSupply.SupplyPageOfData(DataPage.MapToLowerBoundary(RowsPerPage),RowsPerPage),RowsPerPage)
};
}

私人字符串RetrieveData_CacheIt_ThenReturnElement(INT的rowIndex,INT参数:columnIndex)
{
//检索包含所请求的值数据的页面的价值。
DataTable的表= dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(rowIndex位置),RowsPerPage);

// Replace the cached page furthest from the requested cell
// with a new page containing the newly retrieved data.
cachePages[GetIndexToUnusedPage(rowIndex)] = new DataPage(table, rowIndex);

return RetrieveElement(rowIndex, columnIndex);
}

// Returns the index of the cached page most distant from the given index
// and therefore least likely to be reused.
private int GetIndexToUnusedPage(int rowIndex)
{
if (rowIndex > cachePages[0].HighestIndex &&
rowIndex > cachePages[1].HighestIndex)
{
int offsetFromPage0 = rowIndex - cachePages[0].HighestIndex;
int offsetFromPage1 = rowIndex - cachePages[1].HighestIndex;
if (offsetFromPage0 < offsetFromPage1)
{
return 1;
}
return 0;
}
else
{
int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;
int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;
if (offsetFromPage0 < offsetFromPage1)
{
return 1;
}
return 0;
}

}

// Returns a value indicating whether the given row index is contained
// in the given DataPage.
private bool IsRowCachedInPage(int pageNumber, int rowIndex)
{
return rowIndex <= cachePages[pageNumber].HighestIndex &&
rowIndex >= cachePages[pageNumber].LowestIndex;
}

}
}


i have completed my code for DataGridView with virtual data loading and it is working but i want sorting also should work when i will click on column header column. i read idea from this thread http://stackoverflow.com/questions/17087074/c-sharp-datagridview-virtual-mode-enable-sorting

but still could not achieve how to enable sorting when DataGridView virtual mode is enabled.

here i am posting full code and also apologized for posting my big code. so please some one rectify my code or give me small code portion which help me to sort grid data along with virtual data loading. sorting glyph should come too when column header will be clicked.

here is full code

 public partial class Form1 : Form
    {
        private string connectionString =
        "Initial Catalog=Test1;Data Source=BBATRIDIP\\SQLSERVER2008R2;" +
        "Integrated Security=SSPI;Persist Security Info=False";
        private string table = "Orders";

        private Cache memoryCache=null;

        public Form1()
        {
            InitializeComponent();
            this.dataGridView1.VirtualMode = true;
            this.dataGridView1.ReadOnly = true;
            this.dataGridView1.SelectionMode =
            DataGridViewSelectionMode.FullRowSelect;
            this.dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);

        }

        private void dataGridView1_CellValueNeeded(object sender,DataGridViewCellValueEventArgs e)
        {
            e.Value = memoryCache.RetrieveElement(e.RowIndex, e.ColumnIndex);
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            try
            {
                DataRetriever retriever = new DataRetriever(connectionString, table,"OrderID");
                memoryCache = new Cache(retriever, 16);
                foreach (DataColumn column in retriever.Columns)
                {
                    dataGridView1.Columns.Add(column.ColumnName, column.ColumnName);
                }
                this.dataGridView1.RowCount = retriever.RowCount;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Connection could not be established. " + "Verify that the connection string is valid.");
                Application.Exit();
            }

            // Adjust the column widths based on the displayed values. 
            this.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);

        }

        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            // this routine will add row no to HeaderCell which comes left most
            var grid = sender as DataGridView;
            var rowIdx = (e.RowIndex + 1).ToString();

            var centerFormat = new StringFormat()
            {
                // right alignment might actually make more sense for numbers
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };

            var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
            e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
        }

        private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            //this.ValidateChildren();// force value be set to the underlying list.

            string strSortCol = this.dataGridView1.Columns[e.ColumnIndex].Name;
            string strSortOrder = "";

            if (this.dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Ascending)
            {
                this.dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Descending;
                strSortOrder = " ASC";
            }
            else if (this.dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Descending)
            {
                this.dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Ascending;
                strSortOrder = " DESC";
            }

            DataRetriever retriever = new DataRetriever(connectionString, table, strSortCol);
            //dataGridView1.Refresh();
        }


    }


public interface IDataPageRetriever
{
    DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage);
}

public class DataRetriever : IDataPageRetriever
{
    private string tableName;
    private SqlCommand command;
    private string sortColumn;

    public DataRetriever(string connectionString, string tableName, string sortColumn)
    {
        SqlConnection connection = new SqlConnection(connectionString);
        connection.Open();
        command = connection.CreateCommand();
        this.tableName = tableName;
        this.sortColumn = sortColumn;
    }

    private int rowCountValue = -1;

    public int RowCount
    {
        get
        {
            // Return the existing value if it has already been determined. 
            if (rowCountValue != -1)
            {
                return rowCountValue;
            }

            // Retrieve the row count from the database.
            command.CommandText = "SELECT COUNT(*) FROM " + tableName;
            rowCountValue = (int)command.ExecuteScalar();
            return rowCountValue;
        }
    }

    private DataColumnCollection columnsValue;

    public DataColumnCollection Columns
    {
        get
        {
            // Return the existing value if it has already been determined. 
            if (columnsValue != null)
            {
                return columnsValue;
            }

            // Retrieve the column information from the database.
            command.CommandText = "SELECT * FROM " + tableName;
            SqlDataAdapter adapter = new SqlDataAdapter();
            adapter.SelectCommand = command;
            DataTable table = new DataTable();
            table.Locale = System.Globalization.CultureInfo.InvariantCulture;
            adapter.FillSchema(table, SchemaType.Source);
            columnsValue = table.Columns;
            return columnsValue;
        }
    }

    private string commaSeparatedListOfColumnNamesValue = null;

    private string CommaSeparatedListOfColumnNames
    {
        get
        {
            // Return the existing value if it has already been determined. 
            if (commaSeparatedListOfColumnNamesValue != null)
            {
                return commaSeparatedListOfColumnNamesValue;
            }

            // Store a list of column names for use in the 
            // SupplyPageOfData method.
            System.Text.StringBuilder commaSeparatedColumnNames =
                new System.Text.StringBuilder();
            bool firstColumn = true;
            foreach (DataColumn column in Columns)
            {
                if (!firstColumn)
                {
                    commaSeparatedColumnNames.Append(", ");
                }
                commaSeparatedColumnNames.Append(column.ColumnName);
                firstColumn = false;
            }

            commaSeparatedListOfColumnNamesValue =
                commaSeparatedColumnNames.ToString();
            return commaSeparatedListOfColumnNamesValue;
        }
    }

    // Declare variables to be reused by the SupplyPageOfData method. 
    private string columnToSortBy;
    private SqlDataAdapter adapter = new SqlDataAdapter();

    public DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage)
    {
        // Store the name of the ID column. This column must contain unique  
        // values so the SQL below will work properly. 
        if (columnToSortBy == null)
        {
            columnToSortBy = this.Columns[0].ColumnName;
        }

        if (!this.Columns[columnToSortBy].Unique)
        {
            throw new InvalidOperationException(String.Format(
                "Column {0} must contain unique values.", columnToSortBy));
        }

        // Retrieve the specified number of rows from the database, starting 
        // with the row specified by the lowerPageBoundary parameter.
        command.CommandText = "Select Top " + rowsPerPage + " " +
            CommaSeparatedListOfColumnNames + " From " + tableName +
            " WHERE " + columnToSortBy + " NOT IN (SELECT TOP " +
            lowerPageBoundary + " " + columnToSortBy + " From " +
            tableName + " Order By " + sortColumn +
            ") Order By " + sortColumn;
        adapter.SelectCommand = command;

        DataTable table = new DataTable();
        table.Locale = System.Globalization.CultureInfo.InvariantCulture;
        adapter.Fill(table);
        return table;
    }

}


public class Cache
{
    private static int RowsPerPage;

    // Represents one page of data.   
    public struct DataPage
    {
        public DataTable table;
        private int lowestIndexValue;
        private int highestIndexValue;

        public DataPage(DataTable table, int rowIndex)
        {
            this.table = table;
            lowestIndexValue = MapToLowerBoundary(rowIndex);
            highestIndexValue = MapToUpperBoundary(rowIndex);
            System.Diagnostics.Debug.Assert(lowestIndexValue >= 0);
            System.Diagnostics.Debug.Assert(highestIndexValue >= 0);
        }

        public int LowestIndex
        {
            get
            {
                return lowestIndexValue;
            }
        }

        public int HighestIndex
        {
            get
            {
                return highestIndexValue;
            }
        }

        public static int MapToLowerBoundary(int rowIndex)
        {
            // Return the lowest index of a page containing the given index. 
            return (rowIndex / RowsPerPage) * RowsPerPage;
        }

        private static int MapToUpperBoundary(int rowIndex)
        {
            // Return the highest index of a page containing the given index. 
            return MapToLowerBoundary(rowIndex) + RowsPerPage - 1;
        }
    }

    private DataPage[] cachePages;
    private IDataPageRetriever dataSupply;

    public Cache(IDataPageRetriever dataSupplier, int rowsPerPage)
    {
        dataSupply = dataSupplier;
        Cache.RowsPerPage = rowsPerPage;
        LoadFirstTwoPages();
    }

    // Sets the value of the element parameter if the value is in the cache. 
    private bool IfPageCached_ThenSetElement(int rowIndex,
        int columnIndex, ref string element)
    {
        if (IsRowCachedInPage(0, rowIndex))
        {
            element = cachePages[0].table
                .Rows[rowIndex % RowsPerPage][columnIndex].ToString();
            return true;
        }
        else if (IsRowCachedInPage(1, rowIndex))
        {
            element = cachePages[1].table
                .Rows[rowIndex % RowsPerPage][columnIndex].ToString();
            return true;
        }

        return false;
    }

    public string RetrieveElement(int rowIndex, int columnIndex)
    {
        string element = null;

        if (IfPageCached_ThenSetElement(rowIndex, columnIndex, ref element))
        {
            return element;
        }
        else
        {
            return RetrieveData_CacheIt_ThenReturnElement(
                rowIndex, columnIndex);
        }
    }

    private void LoadFirstTwoPages()
    {
        cachePages = new DataPage[]{
        new DataPage(dataSupply.SupplyPageOfData(
            DataPage.MapToLowerBoundary(0), RowsPerPage), 0), 
        new DataPage(dataSupply.SupplyPageOfData(
            DataPage.MapToLowerBoundary(RowsPerPage), 
            RowsPerPage), RowsPerPage)};
    }

    private string RetrieveData_CacheIt_ThenReturnElement(
        int rowIndex, int columnIndex)
    {
        // Retrieve a page worth of data containing the requested value.
        DataTable table = dataSupply.SupplyPageOfData(
            DataPage.MapToLowerBoundary(rowIndex), RowsPerPage);

        // Replace the cached page furthest from the requested cell 
        // with a new page containing the newly retrieved data.
        cachePages[GetIndexToUnusedPage(rowIndex)] = new DataPage(table, rowIndex);

        return RetrieveElement(rowIndex, columnIndex);
    }

    // Returns the index of the cached page most distant from the given index 
    // and therefore least likely to be reused. 
    private int GetIndexToUnusedPage(int rowIndex)
    {
        if (rowIndex > cachePages[0].HighestIndex &&
            rowIndex > cachePages[1].HighestIndex)
        {
            int offsetFromPage0 = rowIndex - cachePages[0].HighestIndex;
            int offsetFromPage1 = rowIndex - cachePages[1].HighestIndex;
            if (offsetFromPage0 < offsetFromPage1)
            {
                return 1;
            }
            return 0;
        }
        else
        {
            int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;
            int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;
            if (offsetFromPage0 < offsetFromPage1)
            {
                return 1;
            }
            return 0;
        }

    }

    // Returns a value indicating whether the given row index is contained 
    // in the given DataPage.  
    private bool IsRowCachedInPage(int pageNumber, int rowIndex)
    {
        return rowIndex <= cachePages[pageNumber].HighestIndex &&
            rowIndex >= cachePages[pageNumber].LowestIndex;
    }

}

解决方案

here i am going post more or less same code for same job but there is bit difference in approach. full code as follows

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
namespace DGVirtualScroll
{
    public partial class Form1 : Form
    {
        private string connectionString =
        "Initial Catalog=Test1;Data Source=BBATRIDIP\\SQLSERVER2008R2;" +
        "Integrated Security=SSPI;Persist Security Info=False";
        private string table = "Orders";
        private string strSortCol = "OrderID";
        private string strSortOrder = "ASC";

        private Cache memoryCache=null;

        public Form1()
        {
            InitializeComponent();

            typeof(DataGridView).InvokeMember("DoubleBuffered",
                BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
                null,
                this.dataGridView1,
                new object[] { true });

            this.dataGridView1.VirtualMode = true;
            this.dataGridView1.ReadOnly = true;
            this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
            this.dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
        }

        private void dataGridView1_CellValueNeeded(object sender,DataGridViewCellValueEventArgs e)
        {
            e.Value = memoryCache.RetrieveElement(e.RowIndex, e.ColumnIndex);
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            Resetsort();
            LoadData(strSortCol, strSortOrder);
        }

        private void Resetsort()
        {
            strSortCol = "OrderID";
            strSortOrder = "ASC";
        }

        private void LoadData(string strSortCol, string strSortOrder)
        {

            dataGridView1.Rows.Clear();
            dataGridView1.Refresh();
            dataGridView1.Columns.Clear();
            dataGridView1.DataSource = null;

            try
            {
                DataRetriever retriever = new DataRetriever(connectionString, table, strSortCol, strSortOrder);
                memoryCache = new Cache(retriever, 16);
                foreach (DataColumn column in retriever.Columns)
                {
                    dataGridView1.Columns.Add(column.ColumnName, column.ColumnName);
                }
                this.dataGridView1.RowCount = retriever.RowCount;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Connection could not be established. " + "Verify that the connection string is valid.");
                Application.Exit();
            }

            // Adjust the column widths based on the displayed values. 
            this.dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
            if (strSortOrder == "ASC")
                this.dataGridView1.Columns[strSortCol].HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Ascending;
            else
                this.dataGridView1.Columns[strSortCol].HeaderCell.SortGlyphDirection = System.Windows.Forms.SortOrder.Descending;

        }

        private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            // this routine will add row no to HeaderCell which comes left most
            var grid = sender as DataGridView;
            var rowIdx = (e.RowIndex + 1).ToString();

            var centerFormat = new StringFormat()
            {
                // right alignment might actually make more sense for numbers
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };

            var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
            e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
        }

        private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (strSortCol.Trim().ToUpper() != this.dataGridView1.Columns[e.ColumnIndex].Name.Trim().ToUpper())
            {
                strSortOrder = "ASC";
            }
            else
            {
                strSortOrder = (this.dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == System.Windows.Forms.SortOrder.Ascending ? "DESC" : "ASC");
            }
            strSortCol = this.dataGridView1.Columns[e.ColumnIndex].Name;
            LoadData(strSortCol, strSortOrder);
        }

        void RefreshGrid()
        {
            //dataGridView1.Rows.Clear();
            //dataGridView1.Refresh();
            //dataGridView1.Columns.Clear();
            //dataGridView1.DataSource = null;
            //LoadData(strSortCol, strSortOrder);
        }

    }
}



******************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace DGVirtualScroll
{
    public interface IDataPageRetriever
    {
        DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage);
    }

    public class DataRetriever : IDataPageRetriever
    {
        private string tableName;
        private SqlCommand command;
        private string sortColumn;
        private string Sortorder;

        public DataRetriever(string connectionString, string tableName, string sortColumn,string Sortorder)
        {
            SqlConnection connection = new SqlConnection(connectionString);
            connection.Open();
            command = connection.CreateCommand();
            this.tableName = tableName;
            this.sortColumn = sortColumn;
            this.Sortorder = (Sortorder.Trim() == "" ? "ASC" : Sortorder.Trim());
        }

        private int rowCountValue = -1;

        public int RowCount
        {
            get
            {
                // Return the existing value if it has already been determined. 
                if (rowCountValue != -1)
                {
                    return rowCountValue;
                }

                // Retrieve the row count from the database.
                command.CommandText = "SELECT COUNT(*) FROM " + tableName;
                rowCountValue = (int)command.ExecuteScalar();
                return rowCountValue;
            }
        }

        private DataColumnCollection columnsValue;

        public DataColumnCollection Columns
        {
            get
            {
                // Return the existing value if it has already been determined. 
                if (columnsValue != null)
                {
                    return columnsValue;
                }

                // Retrieve the column information from the database.
                command.CommandText = "SELECT * FROM " + tableName;
                SqlDataAdapter adapter = new SqlDataAdapter();
                adapter.SelectCommand = command;
                DataTable table = new DataTable();
                table.Locale = System.Globalization.CultureInfo.InvariantCulture;
                adapter.FillSchema(table, SchemaType.Source);
                columnsValue = table.Columns;
                return columnsValue;
            }
        }

        private string commaSeparatedListOfColumnNamesValue = null;

        private string CommaSeparatedListOfColumnNames
        {
            get
            {
                // Return the existing value if it has already been determined. 
                if (commaSeparatedListOfColumnNamesValue != null)
                {
                    return commaSeparatedListOfColumnNamesValue;
                }

                // Store a list of column names for use in the 
                // SupplyPageOfData method.
                System.Text.StringBuilder commaSeparatedColumnNames =
                    new System.Text.StringBuilder();
                bool firstColumn = true;
                foreach (DataColumn column in Columns)
                {
                    if (!firstColumn)
                    {
                        commaSeparatedColumnNames.Append(", ");
                    }
                    commaSeparatedColumnNames.Append(column.ColumnName);
                    firstColumn = false;
                }

                commaSeparatedListOfColumnNamesValue =
                    commaSeparatedColumnNames.ToString();
                return commaSeparatedListOfColumnNamesValue;
            }
        }

        // Declare variables to be reused by the SupplyPageOfData method. 
        private string columnToSortBy;
        private SqlDataAdapter adapter = new SqlDataAdapter();

        public DataTable SupplyPageOfData(int lowerPageBoundary, int rowsPerPage)
        {
            // Store the name of the ID column. This column must contain unique  
            // values so the SQL below will work properly. 
            if (columnToSortBy == null)
            {
                columnToSortBy = this.Columns[0].ColumnName;
            }

            if (!this.Columns[columnToSortBy].Unique)
            {
                throw new InvalidOperationException(String.Format(
                    "Column {0} must contain unique values.", columnToSortBy));
            }

            // Retrieve the specified number of rows from the database, starting 
            // with the row specified by the lowerPageBoundary parameter.
            command.CommandText = "Select Top " + rowsPerPage + " " +
                CommaSeparatedListOfColumnNames + " From " + tableName +
                " WHERE " + columnToSortBy + " NOT IN (SELECT TOP " +
                lowerPageBoundary + " " + columnToSortBy + " From " +
                tableName + " Order By " + sortColumn + " "+Sortorder+
                ") Order By " + sortColumn + " " + Sortorder;
            adapter.SelectCommand = command;

            DataTable table = new DataTable();
            table.Locale = System.Globalization.CultureInfo.InvariantCulture;
            adapter.Fill(table);
            return table;
        }

    }
}

*****************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace DGVirtualScroll
{
    public class Cache
    {
        private static int RowsPerPage;

        // Represents one page of data.   
        public struct DataPage
        {
            public DataTable table;
            private int lowestIndexValue;
            private int highestIndexValue;

            public DataPage(DataTable table, int rowIndex)
            {
                this.table = table;
                lowestIndexValue = MapToLowerBoundary(rowIndex);
                highestIndexValue = MapToUpperBoundary(rowIndex);
                System.Diagnostics.Debug.Assert(lowestIndexValue >= 0);
                System.Diagnostics.Debug.Assert(highestIndexValue >= 0);
            }

            public int LowestIndex
            {
                get
                {
                    return lowestIndexValue;
                }
            }

            public int HighestIndex
            {
                get
                {
                    return highestIndexValue;
                }
            }

            public static int MapToLowerBoundary(int rowIndex)
            {
                // Return the lowest index of a page containing the given index. 
                return (rowIndex / RowsPerPage) * RowsPerPage;
            }

            private static int MapToUpperBoundary(int rowIndex)
            {
                // Return the highest index of a page containing the given index. 
                return MapToLowerBoundary(rowIndex) + RowsPerPage - 1;
            }
        }

        private DataPage[] cachePages;
        private IDataPageRetriever dataSupply;

        public Cache(IDataPageRetriever dataSupplier, int rowsPerPage)
        {
            dataSupply = dataSupplier;
            Cache.RowsPerPage = rowsPerPage;
            LoadFirstTwoPages();
        }

        // Sets the value of the element parameter if the value is in the cache. 
        private bool IfPageCached_ThenSetElement(int rowIndex,
            int columnIndex, ref string element)
        {
            if (IsRowCachedInPage(0, rowIndex))
            {
                element = cachePages[0].table
                    .Rows[rowIndex % RowsPerPage][columnIndex].ToString();
                return true;
            }
            else if (IsRowCachedInPage(1, rowIndex))
            {
                element = cachePages[1].table
                    .Rows[rowIndex % RowsPerPage][columnIndex].ToString();
                return true;
            }

            return false;
        }

        public string RetrieveElement(int rowIndex, int columnIndex)
        {
            string element = null;

            if (IfPageCached_ThenSetElement(rowIndex, columnIndex, ref element))
            {
                return element;
            }
            else
            {
                return RetrieveData_CacheIt_ThenReturnElement(
                    rowIndex, columnIndex);
            }
        }

        private void LoadFirstTwoPages()
        {
            cachePages = new DataPage[]
            {
                new DataPage(dataSupply.SupplyPageOfData(DataPage.MapToLowerBoundary(0), RowsPerPage), 0), 
                new DataPage(dataSupply.SupplyPageOfData(DataPage.MapToLowerBoundary(RowsPerPage), RowsPerPage), RowsPerPage)
            };
        }

        private string RetrieveData_CacheIt_ThenReturnElement(int rowIndex, int columnIndex)
        {
            // Retrieve a page worth of data containing the requested value.
            DataTable table = dataSupply.SupplyPageOfData(
                DataPage.MapToLowerBoundary(rowIndex), RowsPerPage);

            // Replace the cached page furthest from the requested cell 
            // with a new page containing the newly retrieved data.
            cachePages[GetIndexToUnusedPage(rowIndex)] = new DataPage(table, rowIndex);

            return RetrieveElement(rowIndex, columnIndex);
        }

        // Returns the index of the cached page most distant from the given index 
        // and therefore least likely to be reused. 
        private int GetIndexToUnusedPage(int rowIndex)
        {
            if (rowIndex > cachePages[0].HighestIndex &&
                rowIndex > cachePages[1].HighestIndex)
            {
                int offsetFromPage0 = rowIndex - cachePages[0].HighestIndex;
                int offsetFromPage1 = rowIndex - cachePages[1].HighestIndex;
                if (offsetFromPage0 < offsetFromPage1)
                {
                    return 1;
                }
                return 0;
            }
            else
            {
                int offsetFromPage0 = cachePages[0].LowestIndex - rowIndex;
                int offsetFromPage1 = cachePages[1].LowestIndex - rowIndex;
                if (offsetFromPage0 < offsetFromPage1)
                {
                    return 1;
                }
                return 0;
            }

        }

        // Returns a value indicating whether the given row index is contained 
        // in the given DataPage.  
        private bool IsRowCachedInPage(int pageNumber, int rowIndex)
        {
            return rowIndex <= cachePages[pageNumber].HighestIndex &&
                rowIndex >= cachePages[pageNumber].LowestIndex;
        }

    }
}

这篇关于如何排序的DataGridView数据时,虚拟模式启用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆