事情的起因是这样的,因为开发一个软件项目,其中用到了DataGrid控件,然后客户需要点击控件的列头,对内容进行排序,其实内容倒是蛮简单的(纯字符串),咋一看起来,实现应该很简单,应该直接将字符串进行排序显示就完了,于是就写成了类似于这样的代码(这里只是模拟一下,a只是简简单单的包含一个类型为string的公共属性s):
a[] aas = new a[] { new a("scjaosinf"), new a("aedfbsdf"), new a("egwebsd"), new a("xasdfasdg"), new a("21sdvasdfga"), new a("亲爱我没发过后脑勺"), new a("不是的风景嘎三配电间"), new a("下就死的经费"), new a("暗示的过去玩儿该骄傲是") }; ICollectionView View = new ListCollectionView(aas); View.SortDescriptions.Add(new SortDescription("s", ListSortDirection.Ascending));
我们的数据源为假设为aas,然后用户安装某个字段进行排序(这里假如为s),然后我们给这个数据源建一个视图,方便DataGrid去绑定、排序和分组。乍一看,是对的吧,应该没问题的,可用户反映,说排序不正常,最后发现,确实不正常,将上述的代码执行,得到的结果为:
发现没,数字和字母是对的,但汉字就是个错的,难怪客户会说,但客户是上帝,问题还是要解决的,但现在为什么会这样呢?我们先直接对数据源按照字段进行排序,代码为:
1 a[] aas = new a[] 2 { 3 new a("scjaosinf"), 4 new a("aedfbsdf"), 5 new a("egwebsd"), 6 new a("xasdfasdg"), 7 new a("21sdvasdfga"), 8 new a("亲爱我没发过后脑勺"), 9 new a("不是的风景嘎三配电间"),10 new a("下就死的经费"),11 new a("暗示的过去玩儿该骄傲是")12 };13 14 ICollectionView View = new ListCollectionView(aas);15 18 View.Culture = CultureInfo.CurrentCulture;19 20 foreach (var item in View)21 {22 Console.WriteLine((item as a).s);23 }24 Console.WriteLine();25 26 aas = aas.OrderBy(a=>a.s).ToArray();27 foreach (var item in aas)28 {29 Console.WriteLine(item.s);30 }
然后结果为:
这下我特么就奇怪了,为啥后一种方式排序的是对的?!!!
最让我感到无语的就是,网上居然没有搜到关于这个问题的任何描述(百度、bing都试了,我特么就差FQ去Google了)。没办法,只能自己解决了。
经过好多次的尝试后,发现在创建视图前,需要设置视图的区域性信息(以前我一直没管这个信息,谁特么知道这个是干嘛用的,经这次后,血淋淋的教训啊),修改后的代码为:
1 a[] aas = new a[] 2 { 3 new a("scjaosinf"), 4 new a("aedfbsdf"), 5 new a("egwebsd"), 6 new a("xasdfasdg"), 7 new a("21sdvasdfga"), 8 new a("亲爱我没发过后脑勺"), 9 new a("不是的风景嘎三配电间"),10 new a("下就死的经费"),11 new a("暗示的过去玩儿该骄傲是")12 };13 14 ICollectionView View = new ListCollectionView(aas);15 16 //注意这行代码,设置视图的区域性信息为当前区域性对象17 View.Culture = CultureInfo.CurrentCulture;18 19 View.SortDescriptions.Add(new SortDescription("s", ListSortDirection.Ascending));20 21 foreach (var item in View)22 {23 Console.WriteLine((item as a).s);24 }25 Console.WriteLine();26 27 aas = aas.OrderBy(a=>a.s).ToArray();28 foreach (var item in aas)29 {30 Console.WriteLine(item.s);31 }
然后再次执行的结果为:
可以看到,结果已经正常了。
然后再回归到实际的项目中,建立集合视图时,保险起见,一定要视图的区域性信息为当前的区域对象。
ps:被这个破问题搞到现在,我也是疯了,问题改完、项目签入、博文写完,就特么到了这个点了,不早了,睡觉去。。。。