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é
相关产品推荐
相关产品推荐

