C# 在实时数据加载时对ListView列进行排序
我已经根据 及 现在我想在列表视图的列上单击排序。我不知道该怎么做 我是这样做的 缓存类C# 在实时数据加载时对ListView列进行排序,c#,visual-studio,C#,Visual Studio,我已经根据 及 现在我想在列表视图的列上单击排序。我不知道该怎么做 我是这样做的 缓存类 public class Cache { private static int RowsPerPage; // Represents one page of data. public struct DataPage { public DataTable table; private int lowestIndexValue;
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();
}
public IDataPageRetriever DataSupplier
{
get
{
return dataSupply;
}
}
// Sets the value of the element parameter if the value is in the cache.
private bool IfPageCached_ThenSetElement(int rowIndex,
int columnIndex, ref object element)
{
if (IsRowCachedInPage(0, rowIndex))
{
element = cachePages[0].table
.Rows[rowIndex % RowsPerPage][columnIndex];
return true;
}
else if (IsRowCachedInPage(1, rowIndex))
{
element = cachePages[1].table
.Rows[rowIndex % RowsPerPage][columnIndex];
return true;
}
return false;
}
private bool IfPageCached_ThenSetElement(int rowIndex,
string columnName, ref object element)
{
if (IsRowCachedInPage(0, rowIndex))
{
element = cachePages[0].table
.Rows[rowIndex % RowsPerPage][columnName];
return true;
}
else if (IsRowCachedInPage(1, rowIndex))
{
element = cachePages[1].table
.Rows[rowIndex % RowsPerPage][columnName];
return true;
}
return false;
}
public object RetrieveElement(int rowIndex, int columnIndex)
{
object element = null;
if (IfPageCached_ThenSetElement(rowIndex, columnIndex, ref element))
{
return element;
}
else
{
return RetrieveData_CacheIt_ThenReturnElement(
rowIndex, columnIndex);
}
}
public object RetrieveElement(int rowIndex, string columnName)
{
object element = null;
if (IfPageCached_ThenSetElement(rowIndex, columnName, ref element))
{
return element;
}
else
{
return RetrieveData_CacheIt_ThenReturnElement(
rowIndex, columnName);
}
}
public void RemoveElement(int rowIndex)
{
if (IsRowCachedInPage(0, rowIndex))
{
cachePages[0].table.Rows.RemoveAt(rowIndex % RowsPerPage);
}
else if (IsRowCachedInPage(1, rowIndex))
{
cachePages[1].table.Rows.RemoveAt(rowIndex % RowsPerPage);
}
}
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 object 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);
}
private object RetrieveData_CacheIt_ThenReturnElement(
int rowIndex, string columnName)
{
// 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, columnName);
}
// 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;
}
}
公共类缓存
{
私有静态整数行页面;
//表示一页数据。
公共结构数据页
{
公共数据表;
私有int值;
私有int最高索引值;
公共数据页(数据表,int rowIndex)
{
this.table=表格;
lowestIndexValue=MapToLowerBoundary(行索引);
highestIndexValue=MapToUpper边界(rowIndex);
System.Diagnostics.Debug.Assert(lowestIndexValue>=0);
System.Diagnostics.Debug.Assert(highestIndexValue>=0);
}
公共信息索引
{
得到
{
返回lowestIndexValue;
}
}
公共国际高级索引
{
得到
{
返回highestIndexValue;
}
}
公共静态int-MapToLowerBoundary(int-rowIndex)
{
//返回包含给定索引的页面的最低索引。
返回(行索引/行页面)*行页面;
}
私有静态int-MapToUpperBoundary(int-rowIndex)
{
//返回包含给定索引的页面的最高索引。
返回MapToLowerBoundary(rowIndex)+RowsPerPage-1;
}
}
私有数据页[]缓存页;
私有IDataPageRetrier数据源;
公共缓存(IDataPageRetriever数据供应商,int rowsPerPage)
{
数据供应商=数据供应商;
Cache.RowsPerPage=RowsPerPage;
LoadFirstTwoPages();
}
公共数据供应商
{
得到
{
返回数据源;
}
}
//设置元素参数的值(如果该值在缓存中)。
私有bool IfPageCached\u ThenSetElement(int行索引,
int columnIndex,ref对象元素)
{
if(IsRowCachedInPage(0,行索引))
{
元素=缓存页[0]。表
.行[rowIndex%RowsPerPage][columnIndex];
返回true;
}
else if(IsRowCachedInPage(1,行索引))
{
元素=缓存页[1]。表
.行[rowIndex%RowsPerPage][columnIndex];
返回true;
}
返回false;
}
私有bool IfPageCached\u ThenSetElement(int行索引,
字符串(列名称,引用对象元素)
{
if(IsRowCachedInPage(0,行索引))
{
元素=缓存页[0]。表
.Rows[rowsindex%RowsPerPage][columnName];
返回true;
}
else if(IsRowCachedInPage(1,行索引))
{
元素=缓存页[1]。表
.Rows[rowsindex%RowsPerPage][columnName];
返回true;
}
返回false;
}
公共对象检索元素(int行索引、int列索引)
{
object元素=null;
if(IfPageCached\u ThenSetElement(行索引、列索引、引用元素))
{
返回元素;
}
其他的
{
return RetrieveData\u CacheIt\u ThenReturnElement(
行索引、列索引);
}
}
公共对象RetrieveElement(int-rowIndex,string-columnName)
{
object元素=null;
if(IfPageCached\u ThenSetElement(rowIndex、columnName、ref元素))
{
返回元素;
}
其他的
{
return RetrieveData\u CacheIt\u ThenReturnElement(
行索引、列名称);
}
}
public void RemoveElement(int rowIndex)
{
if(IsRowCachedInPage(0,行索引))
{
cachePages[0]。表。行。RemoveAt(行索引%RowsPerPage);
}
else if(IsRowCachedInPage(1,行索引))
{
cachePages[1]。表。行。RemoveAt(行索引%RowsPerPage);
}
}
私有void LoadFirstTwoPages()
{
cachePages=新数据页[]{
新数据页(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(0),RowsPerPage),0),
新数据页(dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(行页面),
RowsPerPage),RowsPerPage)};
}
private object RetrieveData\u CacheIt\u ThenReturnElement(
int行索引,int列索引)
{
//检索包含请求值的一页数据。
DataTable table=dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(rowIndex),RowsPerPage);
//替换离请求单元格最远的缓存页
//使用包含新检索数据的新页面。
cachePages[GetIndexToUnusedPage(rowIndex)]=新数据页(表,rowIndex);
返回RetrieveElement(行索引、列索引);
}
private object RetrieveData\u CacheIt\u ThenReturnElement(
int行索引,字符串列名称)
{
//检索包含请求值的一页数据。
DataTable table=dataSupply.SupplyPageOfData(
DataPage.MapToLowerBoundary(rowIndex),RowsPerPage);
//替换离请求单元格最远的缓存页
//使用包含新检索数据的新页面。
cachePages[GetIndexToUnusedPage(rowIndex)]=新数据页(表,rowIndex);
返回RetrieveElement(行索引、列名称);
}
//返回距离给定索引最远的缓存页的索引
//因此最不可能重复使用。
私有int GetIndexToUnusedPage(int rowIndex)
{
如果(行索引>缓存页[0]。高索引&&
行索引>缓存页[1]
public class DataRetriever : IDataPageRetriever
{
private string tableName;
private string whereClause;
private KeyValuePair<string, object>[] parameters;
public DataRetriever(string tableName, DataTable tableSchema, string whereClause, KeyValuePair<string, object>[] parameters)
{
this.tableName = tableName;
this.whereClause = whereClause;
this.parameters = parameters;
this.tableSchema = tableSchema;
}
private int rowCountValue = -1;
private DataTable tableSchema;
public int RowCount
{
get
{
// Return the existing value if it has already been determined.
if (rowCountValue != -1)
{
return rowCountValue;
}
StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM " + tableName);
if (!string.IsNullOrEmpty(whereClause))
sql.Append(" WHERE " + whereClause);
// Retrieve the row count from the database.
using (ECartableServiceClient client = new ECartableServiceClient())
{
rowCountValue = client.GetRowCount(sql.ToString(), parameters);
client.Close();
}
return rowCountValue;
}
}
private DataColumnCollection columnsValue;
public DataColumnCollection Columns
{
get
{
if (columnsValue == null)
{
if (tableSchema == null)
{
// Retrieve the column information from the database.
using (ECartableServiceClient client = new ECartableServiceClient())
{
columnsValue = client.GetTableSchema("SELECT * FROM " + tableName).Columns;
client.Close();
}
}
else
columnsValue = tableSchema.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;
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.
DataTable table;
string sql = "declare @maxId int\n" +
"SELECT @maxId = MAX(" + columnToSortBy + ") FROM (SELECT TOP " + lowerPageBoundary + " " + columnToSortBy + " FROM " + tableName.Replace("*", "Id") + (string.IsNullOrEmpty(whereClause) ? "" : " WHERE " + whereClause) + " ORDER BY " + columnToSortBy + ") AS t2\n" +
"SELECT TOP " + rowsPerPage + " " +
CommaSeparatedListOfColumnNames + " FROM " + tableName +
" WHERE " + (string.IsNullOrEmpty(whereClause) ? "" : whereClause + " AND ") + columnToSortBy + " > case when @maxId is null then 0 else @maxId end ORDER BY " + columnToSortBy;
using (ECartableServiceClient client = new ECartableServiceClient())
{
table = client.GetDataTable(tableSchema, sql, parameters);
client.Close();
}
return table;
}
}
if (LoadData("vwUser", null, "Users", 50, searchCriteria, null))
ShowData("Users");
private bool LoadData(string tableName, DataTable tableSchema, string cacheName, int rowsPerPage, string criteria, KeyValuePair<string, object>[] parameters)
{
bool result = true;
object[] arguments = new object[6] { tableName, tableSchema, cacheName, rowsPerPage, criteria, parameters };
if (!dictionaryCaches.ContainsKey(cacheName))
{
try
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync(arguments);
formWait = new FormWait();
formWait.ShowDialog(this);
}
catch (System.Data.SqlClient.SqlException)
{
result = false;
MessageBox.Show("Connection could not be established. " +
"Verify that the connection string is valid.");
Application.Exit();
}
}
return result;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
object[] arguments = (object[])e.Argument;
DataRetriever retriever =
new DataRetriever((string)arguments[0], (DataTable)arguments[1], (string)arguments[4], (KeyValuePair<string, object>[])arguments[5]); //"Date_Received >= @d", new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("@d", DateTime.Today) });
dictionaryCaches.Add((string)arguments[2], new Cache(retriever, (int)arguments[3]));
int rowCount = retriever.RowCount;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string connectionstring = @"connectionstring";
SqlConnection connection = new SqlConnection(connectionstring);
connection.Open();
string sql = "select * from Student";
SqlDataAdapter adapter = new SqlDataAdapter(sql,connection);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
DataTable table = dataset.Tables[0];
List<string> list = new List<string>();
listView1.View = View.Details;
foreach (DataColumn item in table.Columns)
{
listView1.Columns.Add(item.ColumnName);
}
foreach (DataRow row in table.Rows)
{
ListViewItem listitem = new ListViewItem(row[0].ToString());
listitem.SubItems.Add(row[1].ToString());
listitem.SubItems.Add(row[2].ToString());
listView1.Items.Add(listitem);
}
}
private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
{
ListViewSorter Sorter = new ListViewSorter();
listView1.ListViewItemSorter = Sorter;
if (!(listView1.ListViewItemSorter is ListViewSorter))
return;
Sorter = (ListViewSorter)listView1.ListViewItemSorter;
if (Sorter.LastSort == e.Column)
{
if (listView1.Sorting == SortOrder.Ascending)
listView1.Sorting = SortOrder.Descending;
else
listView1.Sorting = SortOrder.Ascending;
}
else
{
listView1.Sorting = SortOrder.Descending;
}
Sorter.ByColumn = e.Column;
listView1.Sort();
}
}
public class ListViewSorter : System.Collections.IComparer
{
public int Compare(object o1, object o2)
{
if (!(o1 is ListViewItem))
return (0);
if (!(o2 is ListViewItem))
return (0);
ListViewItem lvi1 = (ListViewItem)o2;
string str1 = lvi1.SubItems[ByColumn].Text;
ListViewItem lvi2 = (ListViewItem)o1;
string str2 = lvi2.SubItems[ByColumn].Text;
int result;
if (lvi1.ListView.Sorting == SortOrder.Ascending)
result = String.Compare(str1, str2);
else
result = String.Compare(str2, str1);
LastSort = ByColumn;
return (result);
}
public int ByColumn
{
get
{
return Column;
}
set
{
Column = value;
}
}
int Column = 0;
public int LastSort
{
get
{
return LastColumn;
}
set
{
LastColumn = value;
}
}
int LastColumn = 0;
}