Avalonia.Controls.DataGrid自动合并列

张开发
2026/4/3 18:03:54 15 分钟阅读
Avalonia.Controls.DataGrid自动合并列
让AI从DataGrid的以下方法入手private void AddNewCellPrivate(DataGridRow row, DataGridColumn column) { DataGridCell newCell new DataGridCell(); PopulateCellContent( isCellEdited: false, dataGridColumn: column, dataGridRow: row, dataGridCell: newCell); if (row.OwningGrid ! null) { newCell.OwningColumn column; newCell.IsVisible column.IsVisible; if (row.OwningGrid.CellTheme is {} cellTheme) { newCell.SetValue(ThemeProperty, cellTheme, BindingPriority.Template); } } row.Cells.Insert(column.Index, newCell); // 智能AutoMerge逻辑比较当前行和下一行的数据 //ApplySmartAutoMerge(row, column, newCell); }最后发现DataGrid并没有为每行数据创建DataGridRow/DataGridCell且还会复用这些创建出来的DataGridCell显其他行的数据。就是说上面的方法只是开始的显示内容是可预测的。多次尝试后发现绘制前都会调用DataGridCell的EnsureGridLine方法于是将合并的代码主要放在其中internal void EnsureGridLine(DataGridColumn lastVisibleColumn) { if (OwningGrid ! null _rightGridLine ! null) { if (OwningGrid.VerticalGridLinesBrush ! null OwningGrid.VerticalGridLinesBrush ! _rightGridLine.Fill) { _rightGridLine.Fill OwningGrid.VerticalGridLinesBrush; } //忽略其他代码 // 调用DataGrid的CheckCellToMerge方法 var (isSameAsPrevious, isSameAsNext) OwningGrid?.CheckCellToMerge(this) ?? (false, false); // 根据不同的组合情况处理底边框和透明度 HandleMergeResult(isSameAsPrevious, isSameAsNext); }至此DataGrid决定如何合并返回当前行与上一行和下一行的数据是否可以合并现在只是简单的比较当前列的内容是否一致。有一个小小的问题在滚动时合并列可能会显示空白。虽说在用的winform版的datagridview也有这个小问题。但新的东西多少有点改进对吧。于是我向AI发出要求。最大的帮助就是判断是否是当前显示的第一列的方法了。/// summary /// 判断指定行是否为可视区域的第一行 /// /summary /// param namerow要检查的行/param /// returnstrue表示是可视区域的第一行false表示不是/returns public bool IsFirstVisibleRow(DataGridRow row) { if (_rowsPresenter null || row null) return false; // 遍历可视区域的所有行找到索引最小的行 int firstVisibleRowIndex int.MaxValue; foreach (Control element in _rowsPresenter.Children) { if (element is DataGridRow visibleRow visibleRow.IsVisible) { firstVisibleRowIndex Math.Min(firstVisibleRowIndex, visibleRow.Index); } } // 如果指定行索引等于可视区域最小索引则为第一行 return row.Index firstVisibleRowIndex; }人工分析后发现DataGridCell的EnsureGridLine不知为何只是lastVisibleColumn有调用并不是行中的全部列。滚动的刷新由DataGridCellsPresenter发起看以下方法internal void EnsureFillerVisibility() { DataGridFillerColumn fillerColumn OwningGrid.ColumnsInternal.FillerColumn; //忽略其他代码 // This must be done after the Filler visibility is determined. This also must be done // regardless of whether or not the filler visibility actually changed values because // we could scroll in a cell that didnt have EnsureGridLine called yet DataGridColumn lastVisibleColumn OwningGrid.ColumnsInternal.LastVisibleColumn; if (lastVisibleColumn ! null) { DataGridCell cell OwningRow.Cells[lastVisibleColumn.Index]; cell.EnsureGridLine(lastVisibleColumn);//不知道为什么只是最后一列需要执行。 } // 检查是否为首行显示如果是则清除合并单元格的透明度 bool isFirstVisualRow (OwningGrid?.IsFirstVisibleRow(OwningRow) true); foreach (DataGridCell cell in OwningRow.Cells) { cell?.ClearMergeOpacity(isFirstVisualRow);//否的时候可能需要恢复透明度 } }

更多文章