为ICollectionView的SortDescriptions添加自定义比较器的实现方案
解决WPF DataGrid日期字符串排序逻辑问题
核心结论
不需要修改构造函数中的someCollection,直接通过ICollectionView(转为ListCollectionView)设置自定义比较器即可实现符合日期逻辑的排序。
实现步骤
1. 编写自定义日期字符串比较器
实现IComparer<MyCustomObject>,处理Date属性的null值、日期解析和排序逻辑:
using System; using System.Collections.Generic; using System.Globalization; public class DateStringComparer : IComparer<MyCustomObject> { public int Compare(MyCustomObject x, MyCustomObject y) { // 处理null场景:将null值排在最前面 if (x.Date == null && y.Date == null) return 0; if (x.Date == null) return -1; if (y.Date == null) return 1; // 按实际日期格式解析(示例格式为MM/dd/yy,需根据你的数据调整) bool xParsed = DateTime.TryParseExact( x.Date, "MM/dd/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime xDate); bool yParsed = DateTime.TryParseExact( y.Date, "MM/dd/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime yDate); // 解析成功则按日期比较,失败则退化为字符串比较 if (xParsed && yParsed) return xDate.CompareTo(yDate); else return string.Compare(x.Date, y.Date, StringComparison.Ordinal); } }
2. 为ICollectionView设置自定义比较器
默认CollectionViewSource.GetDefaultView返回的ICollectionView实际是ListCollectionView,可以强制转换后设置CustomSort属性,同时注意清空原有的SortDescriptions(两者不能同时生效):
修改ViewModel中TableItems的setter:
public ObservableCollection<MyCustomObject> TableItems { get { return tableItems; } set { Set(ref tableItems, value, true); var listView = CollectionViewSource.GetDefaultView(tableItems) as ListCollectionView; if (listView != null) { listView.CustomSort = new DateStringComparer(); listView.SortDescriptions.Clear(); // 必须清空,否则CustomSort不生效 } TableView = listView; } }
如果是在后续逻辑中动态设置排序(比如按钮点击命令):
var listView = TableView as ListCollectionView; if (listView != null) { listView.CustomSort = new DateStringComparer(); listView.SortDescriptions.Clear(); }
常见疑问解答
问:是否需要在构造函数中为someCollection添加自定义比较器?
答:不需要。ICollectionView的排序逻辑是独立于底层集合的,底层集合(ObservableCollection/List)的排序不影响视图层的展示排序,直接在视图集合(ListCollectionView)上设置CustomSort即可满足需求。
内容的提问来源于stack exchange,提问作者5ORBEX
相关产品推荐
相关产品推荐

