WPF DataGrid分页后旧行Item属性显示{DisconnectedItem}问题求助
问题原因与解决方案
核心原因
你直接将DataGridRow作为ItemsSource的数据源是错误的——DataGridRow是WPF的可视化容器,而非数据实体。它的Item属性依赖于所在的DataGrid可视化树上下文:
- 当你替换DataGrid的
ItemsSource时,旧的DataGridRow会被从可视化树中移除,WPF内部会自动断开它与原数据的绑定,将Item标记为{DisconnectedItem},这是WPF的容器回收机制导致的。 - 你存储的是已经被使用过的可视化容器,重复复用这些容器必然触发这个问题。
解决方案:数据与可视化分离
正确的做法是绑定数据实体集合,让DataGrid自动生成和管理DataGridRow容器,而非手动操作这些容器。
1. 定义数据模型
创建对应业务的数据类,存储每行需要展示的数据:
// 示例数据模型,根据实际业务调整属性 public class RowData { public string Column1 { get; set; } public int Column2 { get; set; } // 其他列属性... }
2. 替换数据源为数据集合
将原来存储DataGridRow的集合替换为数据实体集合:
// 用ObservableCollection方便数据变更通知 public ObservableCollection<RowData> Rows { get; } = new ObservableCollection<RowData>();
3. 修改分页逻辑
分页时直接操作数据集合,截取对应页的数据赋值给ItemsSource:
public void Navigate(PaginationDirections direction, int pageNumber = -1) { if (_tableWidget.DataGrid == null || !_tableWidget.Rows.Any()) { return; } // 计算总页数 _totalPages = (int)Math.Ceiling((double)_tableWidget.Rows.Count / _rowsPerPage); _comboBox.ItemsSource = Enumerable.Range(1, _totalPages).ToList(); _comboBox.IsEnabled = _totalPages > 1; _button.IsEnabled = _totalPages > 1; // 处理分页方向 switch (direction) { case PaginationDirections.Previous: if (_currentPage <= 1) break; _currentPage--; break; case PaginationDirections.Next: if (_currentPage >= _totalPages) break; _currentPage++; break; case PaginationDirections.GoTo: if (pageNumber < 1 || pageNumber > _totalPages) break; _currentPage = pageNumber; break; case PaginationDirections.Self: // 保持当前页不变 break; default: break; } // 统一计算当前页需要展示的数据 int skipCount = (_currentPage - 1) * _rowsPerPage; var rowsToDisplay = _tableWidget.Rows.Skip(skipCount).Take(_rowsPerPage).ToList(); _tableWidget.DataGrid.ItemsSource = rowsToDisplay; }
4. 确保列绑定正确
因为你设置了AutoGenerateColumns = false,需要手动将DataGrid列绑定到数据模型的属性,示例:
// 在DataGrid初始化时添加列 _tableWidget.DataGrid.Columns.Add(new DataGridTextColumn { Header = "列1", Binding = new Binding(nameof(RowData.Column1)) }); _tableWidget.DataGrid.Columns.Add(new DataGridTextColumn { Header = "列2", Binding = new Binding(nameof(RowData.Column2)) });
额外说明
- 自定义行/单元格样式:如果之前是通过手动创建
DataGridRow来设置样式,现在可以通过DataGrid的RowStyle或CellStyle属性来实现,通过绑定数据模型的属性控制样式逻辑。 - 数据变更通知:使用
ObservableCollection<RowData>可以自动通知DataGrid数据新增/删除的变化,无需手动刷新ItemsSource。
内容的提问来源于stack exchange,提问作者Oleksandr Kosovan
相关产品推荐
相关产品推荐

