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

为何在ListView的SizeChanged事件中修改列宽会导致控件异常?

WinForms ListView列宽调整异常问题

展示bug的GIF动画

复现代码

using System;
using System.Drawing;
using System.Windows.Forms;

namespace BuggyListView
{
    public partial class Form1 : Form
    {
        private ListView _normalListView;
        private ListView _brokenListView;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            ClientSize = new Size(600, 300);

            _normalListView = new ListView()
            {
                View = View.Details,
                Dock = DockStyle.Left,
                Width = 300
            };
            _normalListView.Columns.Add("Normal ListView");

            _brokenListView = new ListView()
            {
                View = View.Details,
                Dock = DockStyle.Right,
                Width = 300
            };
            _brokenListView.Columns.Add("Buggy ListView");

            Controls.Add(_normalListView);
            Controls.Add(_brokenListView);
            
            for (int i = 0; i < 20; i++) {
                _normalListView.Items.Add($"{i} very loooooooooooooooooooooooooooooooooooooooooooooooooog line");
                _brokenListView.Items.Add($"{i} very loooooooooooooooooooooooooooooooooooooooooooooooooog line");
            }

            _normalListView.Columns[0].Width = _normalListView.ClientRectangle.Width;
            _brokenListView.Columns[0].Width = _brokenListView.ClientRectangle.Width;

            //_normalListView.SizeChanged += _normalListView_SizeChanged;
            _brokenListView.SizeChanged += _brokenListView_SizeChanged;
        }

        private void _normalListView_SizeChanged(object sender, EventArgs e)
        {
            _normalListView.Columns[0].Width = _normalListView.ClientRectangle.Width;
        }

        private void _brokenListView_SizeChanged(object sender, EventArgs e)
        {
            _brokenListView.Columns[0].Width = _brokenListView.ClientRectangle.Width;
        }
    }
}

复现步骤

若上述GIF无法正常显示,可运行代码后按以下操作复现:

  • 将右侧ListView的滚动条向下拖动,使第一项不再是“0”
  • 调整窗口高度,即可触发列宽异常问题

问题成因分析

这是WinForms ListView控件的布局同步时序问题:

  1. 当ListView滚动位置不在顶部时,SizeChanged事件的触发时机早于控件内部滚动区域、可见项布局的更新完成时机。
  2. 此时ClientRectangle.Width的数值确实是正确的,但控件内部尚未完成滚动状态与布局的同步,设置列宽等于该值时,ListView会错误地将垂直滚动条的宽度纳入布局计算,导致列宽被挤压,出现内容显示异常。
  3. 改用Form的SizeChanged事件能解决问题,是因为Form尺寸变化完成后,所有子控件的布局都已同步稳定,此时调整列宽不会出现时序偏差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:05:25