惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
罗磊的独立博客
博客园 - 聂微东
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
F
Fortinet All Blogs
A
About on SuperTechFans
腾讯CDC
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog RSS Feed
IT之家
IT之家
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
宝玉的分享
宝玉的分享
C
Check Point Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Vercel News
Vercel News
爱范儿
爱范儿
Microsoft Security Blog
Microsoft Security Blog
月光博客
月光博客
T
Tailwind CSS Blog
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog

博客园 - 生命体验之kevin-Y

windbg内存占用分析常用命令 如何让Trae IDE调用windbg来分析dump文件 asp.net core如何实现Controller热更新 windbg无法分析dotnetframework3.5的dmp asp.net core通过配置决定AddSingleton的实现类 vscode指定python文件的执行程序 golang离线开发-windows-vscode go语言学习 - caddy配置的一些发现 go语言学习 - caddy添加nacos-gateway 学习jsp-使用IDEA2024社区版 ravendb源代码学习一:服务启动 修整程序集需要 .NET Core 3.0 或更高版本。 打开电脑后一直弹出“交互式检测服务”窗口 Idea2024-java-Maven开发配置 C#获取事件绑定的方法 java.util.zip.DataFormatException: incorrect header check Build Secure Web Services With SOAP Headers and Extensions “System.Net.Http.HttpContent”不包含“ReadAsAsync”的定义 C#入门:如何合理制定方法参数-下 C#入门:如何合理制定方法参数-上 拷贝对象的开源工具类-FastMapper-TinyMapper-Mapster
Avalonia.Controls.DataGrid自动合并列
生命体验之kevin-Y · 2026-02-10 · via 博客园 - 生命体验之kevin-Y

Winform在用的DataGridView修改为通过线条和透明的方式实现了合并列的效果。一段时间也在留意Avalonia.Controls.DataGrid是否也有类似的做法。一直没有心思去看那些代码,水平有限,实在搞不懂XML/Content一类如何实现绘制内容的。借着AI的帮助终于能试着去修改了。

让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决定如何合并,返回当前行与上一行和下一行的数据是否可以合并(现在只是简单的比较当前列的内容是否一致)。

simplemerge

有一个小小的问题,在滚动时合并列可能会显示空白。虽说在用的winform版的datagridview也有这个小问题。但新的东西多少有点改进,对吧。于是我向AI发出要求。最大的帮助就是判断是否是当前显示的第一列的方法了。

/// <summary>
/// 判断指定行是否为可视区域的第一行
/// </summary>
/// <param name="row">要检查的行</param>
/// <returns>true表示是可视区域的第一行,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 didn't 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);//否的时候,可能需要恢复透明度
    }
}

好了,这就是全部修改。代码在gitee

https://gitee.com/kevin2y/Avalonia.Controls.DataGrid/tree/feature/auto-merge-enhancement