Code to remove nested TabPage doesn't always work

I wanted to implement MiddleClick-To-Delete functionality like most tabbed environment in my application that looks like this:

enter image description here

This is just one form with TabControl

which has 2x TabPage

: ActiveItems and archived items.

Both of these pages contain their own TabControl

, which the user can add as many objects as possible TabPage

.

If the user has Active Items selected and they remove the tab, it removes the correct one. If they remove the tab from the archived items, it also removes the correct one. If they move the Active tab to Archive and then delete it, it removes the wrong tab. So in the screenshot above, you cannot see the Archived Items, but there are already 2 tabs. If I move 13571 from Active -> Archive and then delete it (tab # 3, index # 2), it removes tab # 2, index # 1.

// Both the tcActive and tcArchived, the TabControls on tcRoot two Active Items
// and Archived Items tab pages, subscribe to this event
private void tc_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button != System.Windows.Forms.MouseButtons.Left)
        tabPageClicked = e.Location;

    if (e.Button == MouseButtons.Middle)
        DeleteTab();
}

// Passes the TabControl and TabPageIndex to be deleted
private void DeleteTab()
{
    int tpi = GetTabIndex(tabPageClicked);

    if (tcActiveArchive.SelectedIndex.Equals(0))
        DeleteTab(tcActive, tpi);
    else
        DeleteTab(tcArchived, tpi);
}

// Gets the TabPage index from either Active Items page or Archived Items page
private int GetTabIndex(Point p)
{
    if (tcActiveArchive.SelectedIndex.Equals(0))
        return tcActive.TabPages.IndexOf(tcActive.TabPages.Cast<TabPage>().Where((t, i) => tcActive.GetTabRect(i).Contains(p)).First());
    else
        return tcArchived.TabPages.IndexOf(tcArchived.TabPages.Cast<TabPage>().Where((t, i) => tcArchived.GetTabRect(i).Contains(p)).First());
}

// Actual removal of TabPage at index tabIndex from TabControl tc
private void DeleteTab(TabControl tc, int tabIndex)
{
    lastDeleteWasActiveTab = (tcActiveArchive.SelectedIndex.Equals(0));

    //Tab object just stores a string, string[] and bool
    Tab deletedTab = new Tab(tc.TabPages[tabIndex].Text, ((TextBox)tc.TabPages[tabIndex].Controls[0]).Lines, lastDeleteWasActiveTab);

    if (lastDeleteWasActiveTab)
    {
        deletedActiveTabs.Push(deletedTab);
        filesToDelete.Add(mantisDir + tc.TabPages[tabIndex].Text + ".txt");
    }
    else
    {
        deletedArchiveTabs.Push(deletedTab);
        filesToDelete.Add(archiveDir + tc.TabPages[tabIndex].Text + ".txt");
    }

    tc.TabPages.RemoveAt(tabIndex);

    //Try to select the tab to the right of the one that was deleted
    if (tc.TabPages.Count >= tabIndex + 1) 
        tc.SelectedIndex = tabIndex;
    else
        tc.SelectedIndex = tabIndex - 1;

    undoQueue.Push((lastDeleteWasActiveTab) ? UndoEventType.DeleteActive : UndoEventType.DeleteArchive);
}

      

Executing the code for the above condition:

  • MouseDown

    the event is triggered
  • DeleteTab()

  • GetTabIndex

    returns 2
  • DeleteTab(tcArchived, 2);

    called
  • Tab deletedTab

    has all the meanings it should contain, indicating that we are looking at the correct contributor / index.
  • tc.RemoveAt(2)

    called

But it removes the second item, not index 2. Absolutely can't figure out what happened.

+3


source to share


1 answer


Changing this line:

DeleteTab(TabControl tc, int tabIndex)
{
    //other code
    tc.TabPages.RemoveAt(tabIndex);
}

      

To:



TabPage tp = tc.TabPages[tabIndex];
tc.TabPages.Remove(tp);

      

It looks like it works for the use case described in my original post with minimal testing. But I would love to know why it RemoveAt(tabIndex)

doesn't work.

+4


source







All Articles