WPF DataGrid编程实现:保留旧项排序,禁用新项排序
嘿,我来帮你搞定这个需求——让WPF DataGrid里的旧数据正常保持排序功能,新增的条目却不参与排序。咱们可以基于你现有的SortDataGridByMultipleColumns方法改造,核心思路是给新增项添加一个标记属性,然后通过自定义排序比较器,让排序规则只对非新增项生效,新增项可以固定在列表末尾(或者你想要的位置)。
具体实现步骤
- 给数据实体添加新增项标记
首先,在你的数据类里加一个IsNewItem属性,用来区分是否是刚添加的未保存项:
public class YourDataModel : INotifyPropertyChanged { // 你的原有业务属性... private bool _isNewItem; public bool IsNewItem { get => _isNewItem; set { _isNewItem = value; OnPropertyChanged(nameof(IsNewItem)); } } // 实现INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
- 创建自定义排序比较器
这个比较器会判断项是否是新增的,对旧数据执行你原来的多列排序逻辑,对新增项直接跳过排序(让它们固定在末尾):
public class DataGridCustomComparer : IComparer { private readonly Dictionary<int, ListSortDirection> _sortRules; private readonly DataGrid _targetGrid; public DataGridCustomComparer(DataGrid dataGrid, Dictionary<int, ListSortDirection> sortInfo) { _targetGrid = dataGrid; _sortRules = sortInfo; } public int Compare(object x, object y) { var itemX = x as YourDataModel; var itemY = y as YourDataModel; // 处理新增项的排序逻辑:新增项始终排在最后 if (itemX?.IsNewItem == true && itemY?.IsNewItem == false) return 1; if (itemX?.IsNewItem == false && itemY?.IsNewItem == true) return -1; if (itemX?.IsNewItem == true && itemY?.IsNewItem == true) return 0; // 都是新增项,保持添加顺序 // 对旧数据执行原有的多列排序逻辑 foreach (var sortEntry in _sortRules) { var column = _targetGrid.Columns[sortEntry.Key]; // 获取列对应的排序字段名 var sortProperty = column.SortMemberPath ?? column.DisplayMemberBinding?.Path.Path; if (string.IsNullOrEmpty(sortProperty)) continue; var propX = itemX.GetType().GetProperty(sortProperty); var propY = itemY.GetType().GetProperty(sortProperty); if (propX == null || propY == null) continue; var valX = propX.GetValue(itemX); var valY = propY.GetValue(itemY); int compareResult; // 处理可比较类型 if (valX is IComparable compX && valY is IComparable compY) { compareResult = compX.CompareTo(compY); } else { // 非可比较类型按字符串比较 compareResult = string.Compare(valX?.ToString(), valY?.ToString(), StringComparison.Ordinal); } // 根据排序方向调整结果 if (sortEntry.Value == ListSortDirection.Descending) compareResult = -compareResult; // 当前列有排序差异,直接返回结果 if (compareResult != 0) return compareResult; } // 所有排序列都相同,保持原有顺序 return 0; } }
- 改造原有的排序方法
不再用默认的SortDescriptions,而是设置CustomSort来使用我们的自定义比较器:
public static void SortDataGridByMultipleColumns(DataGrid dataGrid, Dictionary<int, ListSortDirection> sortInfo) { // 强制DataGrid退出编辑或新增模式 RemoveNewAndEdit(dataGrid); // 获取数据的CollectionView var collectionView = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource); if (collectionView == null) return; // 应用自定义排序 collectionView.CustomSort = new DataGridCustomComparer(dataGrid, sortInfo); } // 你的原有RemoveNewAndEdit方法(假设已实现) private static void RemoveNewAndEdit(DataGrid dataGrid) { if (dataGrid.IsEditing()) dataGrid.CommitEdit(DataGridEditingUnit.Row, true); if (dataGrid.IsAddingNew()) dataGrid.CancelEdit(); }
- 标记新增项
在添加新项的时候,记得把IsNewItem设为true;当你保存这个新增项后,把IsNewItem设为false,这样它就会加入正常排序了:
// 添加新项示例 var newItem = new YourDataModel { IsNewItem = true }; YourDataCollection.Add(newItem); // 保存新增项后更新标记 private void SaveNewItem(YourDataModel item) { // 这里执行你的保存逻辑(比如写入数据库) // ... // 标记为已保存,参与排序 item.IsNewItem = false; // 重新触发排序 SortDataGridByMultipleColumns(YourDataGrid, YourSortSettingsDictionary); }
额外说明
- 确保你的DataGrid绑定的是
ObservableCollection(或其他支持集合视图的数据源),这样CustomSort的变化会自动刷新界面 - 如果需要调整新增项的位置(比如固定在开头),只需要修改比较器里的返回值即可(把1和-1调换)
内容的提问来源于stack exchange,提问作者Andrew Miller
相关产品推荐
相关产品推荐

