为什么我的列表框抛出异常?我的、抛出、异常、列表

2023-09-04 06:44:49 作者:自讽

好了,我能够创建一个简单的WinForms项目重现一些奇怪的行为,我发现。在设计,制作与列表框(名为LBX)锚上,左,右,下,和一个按钮(按钮1)表单。现在,窗体的code是在这里:

Okay, I was able to create a simple WinForms project that reproduces some strange behavior I found. In the designer, make a Form with a ListBox (named lbx) Anchored Top,Left,Right,Bottom, and a Button (button1). Now, the Form's code is here:

using System;
using System.Windows.Forms;

namespace ListBoxKaboom
{
    public partial class Form1 : Form
    {
        private bool _initFinished = false;

        public Form1()
        {
            InitializeComponent();

            this._initFinished = true;

            this.Height += 100;
            this.Height -= 50;
            this.Height += 50;
        }

        private void lbx_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.button1.Enabled = (this.lbx.SelectedItem != null);
        }

        protected override void OnLayout(LayoutEventArgs e)
        {
            if (_initFinished)
            {
                int lines = (this.lbx.Height - 4) / this.lbx.ItemHeight;

                this.SuspendLayout();
                while (lines < this.lbx.Items.Count)
                {
                    this.lbx.Items.RemoveAt(this.lbx.Items.Count - 1);
                }

                while (lines > this.lbx.Items.Count)
                {
                    this.lbx.Items.Add("Item " + (this.lbx.Items.Count + 1).ToString());
                }
                this.ResumeLayout();
            }

            base.OnLayout(e);
        }
    }
}

请注意以下说明: 运行它,单击任何列表框中的项目,并使用箭头键向下移动到足以使列表框滚动。 KABOOM。异常(有时NullReferenceException异常,有时IndexOutOfBoundsException异常)。任何想法,为什么?另外,我认为项目是为了,但他们没有。那是没有得到通过的WinForms妥善处理还是我做错了什么这只是一个愚蠢的角落呢?

PLEASE NOTE THE FOLLOWING INSTRUCTIONS: Run this, click any of the items in the list box, and use the arrow keys to move down far enough to cause the list box to scroll. Kaboom. Exception (sometimes NullReferenceException, sometimes IndexOutOfBoundsException). Any ideas why? Also, I would think that the items would be in order, but they're not. Is this just a goofy corner case that didn't get handled properly by WinForms or am I doing something wrong?

堆栈跟踪:

在System.Windows.Forms.ListBox.NativeUpdateSelection()

at System.Windows.Forms.ListBox.NativeUpdateSelection()

在System.Windows.Forms.ListBox.SelectedObjectCollection.EnsureUpToDate()

at System.Windows.Forms.ListBox.SelectedObjectCollection.EnsureUpToDate()

在System.Windows.Forms.ListBox.SelectedObjectCollection.get_InnerArray()

at System.Windows.Forms.ListBox.SelectedObjectCollection.get_InnerArray()

在System.Windows.Forms.ListBox.SelectedObjectCollection.get_Item(的Int32指数)

at System.Windows.Forms.ListBox.SelectedObjectCollection.get_Item(Int32 index)

在System.Windows.Forms.ListBox.get_SelectedItem()

at System.Windows.Forms.ListBox.get_SelectedItem()

推荐答案

我复制/粘贴到一个空表,并得到一个计算器例外。看着它,手法布局事件内的项目,我会说你应该得到更好一点。

I Copy/Pasted it to an empty Form and get a StackOverflow exception. Looking at it, with manipulation of the Items inside a Layout event I would say you deserve little better.

我意识到这可能是别的东西简单化,但也仅仅是有限的,你可以在EDS做些什么。

I realize this may be a simplification of something else, but there simply are limits to what you can do in a EDS.

我最好的猜测:该ResumeLayout触发递归布局操作。你可以尝试用兄弟姐妹干到_initFinished,但我会建议在这里重新思考巡演设计。

My best guess: The ResumeLayout triggers a recursive layout operation. You could try to stem it with a sibling to _initFinished but I would suggest rethinking tour design here.

我复制/粘贴错了,是我不好(用布局事件)。

I copy/pasted wrong, my bad (used layout event).

二试: 基于两个while循环我预计项目字符串是为了,也没有垂直滚动条。很显然,列表框混乱,表现出垂直滚动范围,并与项目外的顺序。因此,一些错误已经是present在列表框的内部,等待滚动。我也可以用鼠标重现出来。

Second try: based on the two while-loops I would expect the Item strings to be in order, and no vertical scrollbar. It is clear that the listbox is confused, showing vertical scroll range and with the items out-of-order. So some 'error' is already present in the internals of the Listbox, waiting for a Scroll. I can also reproduce it with the mouse.

有一个解决办法:你应该可以使用Resize事件,以获得预期的效果

A workaround: You should be able to get the desired effect using the Resize event.

尝试解释:列表框(的非托管部分)由(多)添加/ RemoveAt悬浮布局操作迷糊。最后一个项目是画在错误的地方,并列表框不能计算像素到项目。

Attempt to an explanation: The (unmanaged part of the) Listbox gets confused by (multiple) Add/RemoveAt operations with suspended Layout. The last items are drawn at the wrong place, and the Listbox can't compute pixel-to-item.