例子
共有52行记录的数据表MyTable的列Letter(数据是可能由数字打头的字符串)数据如下:
0.A
1.B
2.C
3.D
……
9.J
10.K
11.L
12.m
13.N
……
19.T
20.U
21.V
22.W
23.X
……
A
B
C
D
……
W
X
Y
Z
如果直接使用Select Letter From MyTable Order by Letter,则获取的DataTable行排序如下:
0.A
1.B
11.L
12.m
13.N
……
2.C
20.U
21.V
22.W
23.X
……
A
B
C
D
……
W
X
Y
Z
可用如下方法解决:
private DataTable DeepCloneDataTable(DataTable source)
{
DataTable clonedTable = source.Clone();
DataRow newRow;
foreach (DataRow row in source.Rows)
{
newRow = clonedTable.NewRow();
foreach (DataColumn column in source.Columns)
{
newRow[column.ColumnName] = row[column];
}
clonedTable.Rows.Add(newRow);
}
return clonedTable;
}
private void sortDataTableByColumnName(DataTable needToSortDataTable,string columnName)
{
DataTable dataTable = DeepCloneDataTable(needToSortDataTable);
Match match;
List<DataRow> sortedRows = dataTable.AsEnumerable()
.OrderBy(row =>
{
match = Regex.Match(row[columnName].ToString(), @"^\d+(\.\d+)?"); //匹配开头的整数或小数
if (match.Success)
{
return double.Parse(match.Value);
}
else
{
return double.MaxValue;
}
})
.ThenBy(row => row[columnName].ToString())
.ToList();
needToSortDataTable.Rows.Clear();
//本来想直接用needToSortDataTable的Rows.Add方法直接添加行的,但是会报错该行已属于另一个表,把这里的dataTable的Rows.Clear也不管用,所以使用了这种方法。
foreach (DataRow row in sortedRows)
{
DataRow dataRow = needToSortDataTable.NewRow();
foreach (DataColumn dataColumn in needToSortDataTable.Columns)
{
dataRow[dataColumn.ColumnName] = row[dataColumn.ColumnName];
}
needToSortDataTable.Rows.Add(dataRow);
}
}