Search code examples
winformstabcontroltabpage

Winforms throws ArgumentOutOfRangeException when setting TabPage.Text


I have code like this

someTabPage.Text = "hello";

where someTabPage is a non-null instance of System.Windows.Forms.TabPage created by the Winforms designer.

Occasionally (no one can reproduce this yet) this exception is thrown

[System.ArgumentOutOfRangeException] InvalidArgument=Value of '-1' is not valid for 'index'.
Parameter name: index
  at System.Windows.Forms.TabControl.SetTabPage(Int32 index, TabPage tabPage, TCITEM_T tcitem)
  at System.Windows.Forms.TabControl.UpdateTab(TabPage tabPage)
  at System.Windows.Forms.TabPage.UpdateParent()
  at System.Windows.Forms.TabPage.set_Text(String value)
  at my code which calls the setter

I am looking at the source starting from this point in the call stack but I can't imagine what is wrong. As Ginosaji suggests in the comments, it seems that the parent-child relationship is broken - the TabPage is pointing to its parent TabControl, but the parent is not holding the child in its collection. I would think "race condition", but only the UI thread should be able to touch Winforms controls.

It might be worth noting that this TabControl is nested in another TabControl, but that doesn't give me any ideas.

Does anyone know why this could be happening?

Progress

I caught it in the debugger and confirmed that the parent-child relationship is indeed broken.

? tabPageProblem.Parent
{System.Windows.Forms.TabControl, TabPages.Count: 2, TabPages[0]: TabPage: {Unit Data}}
    System.Windows.Forms.TabControl: {System.Windows.Forms.TabControl, TabPages.Count: 2, TabPages[0]: TabPage: {Unit Data}}
? tabPageProblem.Parent.Name
"tabControlParent"
? tabControlParent.TabPages.Contains(tabPageProblem)
False

The tab page still has its Parent set, but the parent does not Contain the tab page.

Unfortunately, I still don't know how it got into this state.


Solution

  • I've been running into this error with .TabPages.Add and finally found a consistent repro and a solution that may help you:

    Add in this new line:

        someTabPage.PerformLayout();
        someTabPage.Text = "hello";