[英]C#: Custom sort of DataGridView
我需要使用自然排序(在資源管理器中)對DataGridView進行排序,以便數字和文本(在同一列中)自然排序,而不是按字母順序排序(以便“位置3”位於“位置20”之前,等等)。 我有一個DataGridView,我將DataView設置為DataSource。 DataView包含一個DataTable,它是使用數據庫中的某些值創建的。 列類型是字符串。 我有一個IComparer,它做了它應該做的,但我無法弄清楚如何使用它,因為我無法找到如何進行排序。 DataGridView.SortCompare事件是完美的 ,因為它是數據綁定的,所以不起作用。 DataView.Sort只接受具有列名和排序順序的字符串。
很煩人。 試圖在StackOverflow上閱讀相關問題,並搜索谷歌的很多和很多,但我真的找不到這個。 只有我真正找到的東西是使用dataview的Sort(字符串)方法,因為它按字母順序排序。
有沒有人知道如何做到這一點沒有太多麻煩? 它應該是別人而不是我這個? 我真的不想重新實現整個datagridview或dataview類,只是為了獲得自定義排序...
更新 :如果有人想知道,我仍然在尋找這個問題的好答案。 雖然與此同時,我最終創建了自己的簡單表類,然后手動將其提供給datagridview。 覆蓋SortCompare方法。 有點煩人,但並不太難,因為我只需要顯示值(沒有編輯或任何東西),因此可以將所有內容轉換為字符串。
這段代碼應該有效。 它類似於ListView的ListViewItemSorter。 使用IComparer。
使用:
private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
MyDataGridHelper.DataGridSort(dgv, e.ColumnIndex);
}
MyDataGridHelper.cs:
public class MyDataGridHelper
{
public static void DataGridSort(DataGridView dgv, int column)
{
DataGridViewCustomSorter dgvSorter = null;
if (dgv.Tag == null || !(dgv.Tag is IComparer))
{
dgvSorter = new DataGridViewCustomSorter(dgv);
dgv.Tag = dgvSorter;
}
else
{
dgvSorter = (DataGridViewCustomSorter)dgv.Tag;
}
dgvSorter.SortColumn = column;
dgv.Sort(dgvSorter);
}
private class DataGridViewCustomSorter : IComparer
{
private int ColumnIndex;
private SortOrder OrderOfSort;
private DataGridView myDataGridView;
private TypeCode mySortTypeCode;
public DataGridViewCustomSorter(DataGridView dgv)
{
myDataGridView = dgv;
mySortTypeCode = Type.GetTypeCode(Type.GetType("System.String"));
ColumnIndex = 0;
OrderOfSort = SortOrder.None;
}
public int Compare(object x, object y)
{
int result;
DataGridViewRow dgvX, dgvY;
dgvX = (DataGridViewRow)x;
dgvY = (DataGridViewRow)y;
string sx = dgvX.Cells[ColumnIndex].Value.ToString();
string sy = dgvY.Cells[ColumnIndex].Value.ToString();
//null handling
if (sx == String.Empty && sy == String.Empty)
result = 0;
else if (sx == String.Empty && sy != String.Empty)
result = -1;
else if (sx != String.Empty && sy == String.Empty)
result = 1;
else
{
switch (mySortTypeCode)
{
case TypeCode.Decimal:
Decimal nx = Convert.ToDecimal(sx);
Decimal ny = Convert.ToDecimal(sy);
result = nx.CompareTo(ny);
break;
case TypeCode.DateTime:
DateTime dx = Convert.ToDateTime(sx);
DateTime dy = Convert.ToDateTime(sy);
result = dx.CompareTo(dy);
break;
case TypeCode.String:
result = (new CaseInsensitiveComparer()).Compare(sx, sy);
break;
default:
result = (new CaseInsensitiveComparer()).Compare(sx, sy);
break;
}
}
if (OrderOfSort == SortOrder.Descending)
result = (-result);
return result;
}
public int SortColumn
{
set
{
if (ColumnIndex == value)
{
OrderOfSort = (OrderOfSort == SortOrder.Descending ? SortOrder.Ascending : SortOrder.Descending);
}
ColumnIndex = value;
try
{
mySortTypeCode = Type.GetTypeCode(Type.GetType((myDataGridView.Columns[ColumnIndex]).Tag.ToString()));
}
catch
{
mySortTypeCode = TypeCode.String;
}
}
get { return ColumnIndex; }
}
public SortOrder Order
{
set { OrderOfSort = value; }
get { return OrderOfSort; }
}
} //end class DataGridViewCustomSorter
} //end class MyDataGridHelper
這里有一些解決方案“ 使用SortCompare事件進行 自定義排序 ”和“ 使用IComparer接口進行自定義排序 ”:
您可以創建2個隱藏列。 將文本部分分配給第一個隱藏列,將數字部分分配給第二個隱藏列。 現在按這些隱藏列排序(第一列的alpha排序和第二列的數字排序)。
通過這種方式,您可以保留原始列以進行顯示,並使用2個隱藏列進行排序。
您可以將排序邏輯移動到數據庫查詢中,並讓它返回具有正確排序順序的其他列。
然后(沿着@True C Sharp的回答)你可以有一個包含這個值的隱藏列,並按此而不是顯示列進行排序。
這假定用於確定排序順序的邏輯可以在SQL中執行。 如果用於確定排序順序的算法很復雜,則這可能不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.