silverlight4/5 修改源码实现 DataGrid 中文按拼音排序
silverlight3的DataGrid中文按拼音排序,silverlight4/5不是,本文通过修改SDK DLL实现silverlight3的拼音排序。
老项目还是silverlight3的,升级silverlight4后,DataGrid不按拼音排序,用户意见很大,只得着手解决。网上常见解决方案是捕捉点击事件,自定义排序,我也照葫芦画瓢实现了,但用到DataGrid地方都要修改,以后用到DataGrid都要带个小尾巴,着实不便。继续问Google,发现国外论坛一片骂声,silverlight5没提供源代码,也就是说...天可怜见,DataGrid有源代码,silverlight3/4都有源代码,但silverlight5没有,能升级到4也可以。
源码位于:Program Files (x86)\Microsoft SDKs\Silverlight\v3.0\Toolkit\Jul09\Source\Source code.zip
DataGrid在System.Windows.Controls.Data项目中,将该项目加入到我的项目解决方案中,调试得出排序实现在System.Windows.Data.dll,打开System.Windows.Data项目,最终找到排序实现位于PagedCollectionView.cs:private List<object> SortList(List<object> list)。
对比silverlight3、silverlight4代码,差别很简单,注释掉的seq =为silverlight4的代码,可见只是将comparer去到,ThenBy是多列排序,OrderBy是单列排序。调试通过,DataGrid拼音排序正常。
switch (sort.Direction) { case System.ComponentModel.ListSortDirection.Ascending: if (orderedEnum != null) { // thenby //seq = orderedEnum.ThenBy(item => InvokePath(item, propertyPath, propertyType), comparer); seq = orderedEnum.ThenBy(item => InvokePath(item, propertyPath, propertyType)); } else { // orderby //seq = seq.OrderBy(item => InvokePath(item, propertyPath, propertyType), comparer); seq = seq.OrderBy(item => InvokePath(item, propertyPath, propertyType)); } break; case System.ComponentModel.ListSortDirection.Descending: if (orderedEnum != null) { // thenby //seq = orderedEnum.ThenByDescending(item => InvokePath(item, propertyPath, propertyType), comparer); seq = orderedEnum.ThenByDescending(item => InvokePath(item, propertyPath, propertyType)); } else { // orderby //seq = seq.OrderByDescending(item => InvokePath(item, propertyPath, propertyType), comparer); seq = seq.OrderByDescending(item => InvokePath(item, propertyPath, propertyType)); } break; default: break; }
经查仅 System.Windows.Controls.Data.DataForm.Toolkit.dll 也依赖 System.Windows.Data.dll,同System.Windows.Controls.Data重新编译即可。我的解决办法是直接替换微软原始dll,多快好省。
没有升级到silverlight5毕竟不爽,接下来研究反编译,先反编译为C#代码,确认排序方式与silverlight4基本一致。反编译后的C#代码没法直接编译,问Google了解到使用ilasm反编译为IL汇编,vs2012的ilasm路径:
Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\
用ilasm打开System.Windows.Data.dll,转储为sort.IL文件,排序代码位于:
SortList(class [mscorlib]System.Collections.Generic.List`1<object> list) cil managed
{
}
用silverlight4的代码替换掉silverlight5。接下来用ilasm命令将IL重新编译为DLL,路径:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319
由于是强签名的,借用silverlight4源码中带的RiaClient.snk,编译命令:
ilasm d:\temp\5\sort.il /output=d:\temp\5\System.Windows.Data.dll /dll /RESOURCE=d:\temp\5\sort.res /key=d:\temp\5\RiaClient.snk
使用.Net Reflector查看System.Windows.Data.dll的PublicKeyToken:
// Assembly System.Windows.Data, Version 5.0.5.0
Location: D:\Temp\5\System.Windows.Data.dll
Name: System.Windows.Data, Version=5.0.5.0, Culture=neutral, PublicKeyToken=1dd0be75816bbb62
Type: Library
接下来反编译DataGrid所在的System.Windows.Controls.Data.dll为dg.IL文件,修改依赖System.Windows.Data.dll的PublicKeyToken:
.assembly extern System.Windows.Data
{
.publickeytoken = (31 BF 38 56 AD 36 4E 35 ) // 1.8V.6N5
.ver 5:0:5:0
}
使用1dd0be75816bbb62,替换掉31 BF 38 56 AD 36 4E 35:
.assembly extern System.Windows.Data
{
.publickeytoken = (1D D0 BE 75 81 6B BB 62 ) // 1.8V.6N5
.ver 5:0:5:0
}
重新编译为dll,命令:
ilasm d:\temp\5\dg.il /output=d:\temp\5\System.Windows.Controls.Data.dll /dll/RESOURCE=d:\temp\5\dg.res /key=d:\temp\5\RiaClient.snk
System.Windows.Controls.Data.DataForm.Toolkit.dll 也同 System.Windows.Controls.Data.dll 一样处理。替换掉微软原始的dll,测试通过。
已修改好的DLL下载: