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

C# 开启双缓冲的TableLayoutPanel删除行后界面不更新问题求助

解决方案

以下修改均保留双缓冲特性,可同时解决闪烁和删除行后不刷新的问题:

1. 修正自定义DBLayoutPanel类配置

开启双缓冲时遗漏了布局变更触发重绘的相关配置,补充后代码如下:

public partial class DBLayoutPanel : TableLayoutPanel
{
    public DBLayoutPanel()
    {
        InitializeComponent();
        // 新增ResizeRedraw样式,布局变更时自动触发重绘
        SetStyle(ControlStyles.AllPaintingInWmPaint |
          ControlStyles.OptimizedDoubleBuffer |
          ControlStyles.UserPaint |
          ControlStyles.ResizeRedraw, true);
        // 显式开启双缓冲属性
        DoubleBuffered = true;
    }

    public DBLayoutPanel(IContainer container)
    {
        container.Add(this);
        InitializeComponent();
        SetStyle(ControlStyles.AllPaintingInWmPaint |
          ControlStyles.OptimizedDoubleBuffer |
          ControlStyles.UserPaint |
          ControlStyles.ResizeRedraw, true);
        DoubleBuffered = true;
    }

    // 重写控件移除事件,删除行控件后自动触发重绘
    protected override void OnControlRemoved(ControlEventArgs e)
    {
        base.OnControlRemoved(e);
        Invalidate();
    }
}

2. 优化布局更新逻辑

原有布局更新逻辑未同步行列样式,也没有主动触发重绘,修改后代码如下:

private void updateUI()
{
    ActionLayoutPanel.SuspendLayout();
    // 按DateTime排序所有事件
    firingEventList.Sort((x, y) => DateTime.Compare(x.eventTime, y.eventTime));
    // 同步RowCount和RowStyles,避免布局计算异常
    ActionLayoutPanel.RowCount = firingEventList.Count + 2;
    for (int i = ActionLayoutPanel.RowStyles.Count - 1; i >= ActionLayoutPanel.RowCount; i--)
    {
        ActionLayoutPanel.RowStyles.RemoveAt(i);
    }
    // 重新设置控件行列位置
    for (int i = 0; i < firingEventList.Count; i++)
    {
         ActionLayoutPanel.SetRow(firingEventList[i].LabelTimeControl, i + 2);
         ActionLayoutPanel.SetColumn(firingEventList[i].LabelTimeControl, 0);
         ActionLayoutPanel.SetRow(firingEventList[i].LabelActionControl, i + 2);
         ActionLayoutPanel.SetColumn(firingEventList[i].LabelActionControl, 1);
         ActionLayoutPanel.SetRow(firingEventList[i].LabelDataControl, i + 2);
         ActionLayoutPanel.SetColumn(firingEventList[i].LabelDataControl, 2);
         ActionLayoutPanel.SetRow(firingEventList[i].ButtonControl, i + 2);
         ActionLayoutPanel.SetColumn(firingEventList[i].ButtonControl, 3);
   }
   // 传入true立即执行挂起的布局计算
   ActionLayoutPanel.ResumeLayout(true);
   // 强制控件立即重绘,无需等待系统绘制消息
   ActionLayoutPanel.Refresh();
}

问题原理说明

开启ControlStyles.UserPaint后,TableLayoutPanel的默认绘制逻辑会被接管,删除控件、调整布局后不会主动触发重绘请求,只有窗口收到系统WM_PAINT消息(比如切换窗口后回到当前界面)时才会执行绘制。以上修改从两个维度解决问题:

  • 补充控件样式和事件重写,让控件在布局变更、控件移除时自动发起重绘请求
  • 修正布局逻辑的同步问题,避免布局计算异常导致的绘制错误,同时主动触发重绘

内容的提问来源于stack exchange,提问作者Antoine Boré

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:12:01