Question

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.

Was it helpful?

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";

OTHER TIPS

You mentioned the issue happens in a child TabControl... Is the tabpage containing this child TabControl inactive when the Text is set? (Meaning a different tabpage of the parent TabControl is in the foreground.) I believe that while the child TabControl is not visible (being in a "background" tabpage) it has a tendency to behave unexpectedly.

Here is the workaround I used:

If tabControl.TabPages.Contains(tabPage) Then
    tabPage.Text = "the text"
ElseIf tabPage.Parent IsNot Nothing Then
    logger.Warn("there is still a problem with this tab page, parent is {0}", tabPage.Parent)
End If
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top