You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#的DataGridView中添加带图片的标签以实现事件查看器

实现C# DataGridView事件查看器的方案

核心思路

要实现类似系统事件查看器的效果,核心是做自定义DataGridView行展开+单元格复合控件:每行默认显示事件摘要信息,点击展开按钮后显示详细的事件内容,同时在单元格内整合文本标签与展开/折叠按钮。


步骤1:创建自定义DataGridView单元格与列

先定义包含标签和按钮的复合单元格,继承自DataGridViewCell,再关联对应的自定义列:

// 自定义单元格:整合文本标签与展开按钮
public class EventDetailCell : DataGridViewCell
{
    private bool _isExpanded;
    // 存储事件详细内容
    public string EventDetails { get; set; }

    protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates elementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
    {
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

        // 绘制事件摘要文本
        var labelRect = new Rectangle(cellBounds.X + 10, cellBounds.Y + 5, cellBounds.Width - 60, cellBounds.Height - 10);
        graphics.DrawString(formattedValue?.ToString(), cellStyle.Font, new SolidBrush(cellStyle.ForeColor), labelRect);

        // 绘制展开/折叠按钮
        var buttonRect = new Rectangle(cellBounds.Right - 50, cellBounds.Y + 5, 40, cellBounds.Height - 10);
        var buttonText = _isExpanded ? "-" : "+";
        graphics.FillRectangle(new SolidBrush(Color.LightGray), buttonRect);
        graphics.DrawRectangle(Pens.Black, buttonRect);
        var buttonTextSize = graphics.MeasureString(buttonText, cellStyle.Font);
        graphics.DrawString(buttonText, cellStyle.Font, Brushes.Black, 
            buttonRect.X + (buttonRect.Width - buttonTextSize.Width)/2, 
            buttonRect.Y + (buttonRect.Height - buttonTextSize.Height)/2);

        // 展开状态下绘制详细内容
        if (_isExpanded)
        {
            var detailRect = new Rectangle(cellBounds.X + 10, cellBounds.Y + 45, cellBounds.Width - 20, cellBounds.Height - 50);
            StringFormat format = new StringFormat { LineAlignment = StringAlignment.Near, Trimming = StringTrimming.None };
            graphics.DrawString(EventDetails, new Font(cellStyle.Font, FontStyle.Regular), Brushes.DarkGray, detailRect, format);
        }
    }

    // 处理按钮点击,切换展开状态
    protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
    {
        base.OnMouseClick(e);
        var cellBounds = DataGridView.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
        var buttonRect = new Rectangle(cellBounds.Right - 50, cellBounds.Y + 5, 40, cellBounds.Height - 10);
        
        if (buttonRect.Contains(e.Location))
        {
            _isExpanded = !_isExpanded;
            // 调整行高适配展开/折叠状态
            DataGridView.Rows[e.RowIndex].Height = _isExpanded ? 150 : 40;
            DataGridView.InvalidateCell(e.ColumnIndex, e.RowIndex);
        }
    }
}

// 自定义列,绑定自定义单元格
public class EventDetailColumn : DataGridViewColumn
{
    public EventDetailColumn()
    {
        CellTemplate = new EventDetailCell();
        Width = 600;
        HeaderText = "事件描述";
    }
}

步骤2:配置DataGridView并绑定数据

在WinForm窗体中初始化DataGridView,添加自定义列与其他事件字段列,再绑定模拟数据:

public partial class EventViewerForm : Form
{
    public EventViewerForm()
    {
        InitializeComponent();
        InitDataGridView();
        LoadSampleEvents();
    }

    private void InitDataGridView()
    {
        // 添加自定义事件描述列
        dataGridView1.Columns.Add(new EventDetailColumn());
        // 添加标准事件字段列
        dataGridView1.Columns.Add("EventId", "事件ID");
        dataGridView1.Columns.Add("Level", "级别");
        dataGridView1.Columns.Add("Source", "来源");

        // 设置默认行高
        dataGridView1.RowTemplate.Height = 40;
        // 禁止编辑单元格
        dataGridView1.ReadOnly = true;
    }

    private void LoadSampleEvents()
    {
        var events = new List<EventItem>
        {
            new EventItem 
            { 
                Description = "系统启动完成", 
                EventId = 1001, 
                Level = "信息", 
                Source = "Kernel-General",
                Details = "操作系统已完成启动过程,耗时2分15秒。\n启动项加载:\n- 系统服务A\n- 系统服务B"
            },
            new EventItem 
            { 
                Description = "磁盘空间不足", 
                EventId = 2001, 
                Level = "警告", 
                Source = "Disk",
                Details = "磁盘C剩余空间仅5%,建议清理无用文件。\n当前使用空间:95GB,总空间:100GB"
            }
        };

        foreach (var evt in events)
        {
            int rowIndex = dataGridView1.Rows.Add();
            var cell = (EventDetailCell)dataGridView1.Rows[rowIndex].Cells[0];
            cell.Value = evt.Description;
            cell.EventDetails = evt.Details;
            dataGridView1.Rows[rowIndex].Cells["EventId"].Value = evt.EventId;
            dataGridView1.Rows[rowIndex].Cells["Level"].Value = evt.Level;
            dataGridView1.Rows[rowIndex].Cells["Source"].Value = evt.Source;
        }
    }
}

// 事件数据模型
public class EventItem
{
    public string Description { get; set; }
    public int EventId { get; set; }
    public string Level { get; set; }
    public string Source { get; set; }
    public string Details { get; set; }
}

额外优化建议

  • 给不同级别事件设置行颜色:比如警告行用浅黄背景,错误行用浅红背景
  • 支持双击行触发展开/折叠
  • 给详细内容区域添加边框,区分摘要与详情模块

内容的提问来源于stack exchange,提问作者Cak Dham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:05:13