Код для удаления вложенной страницы не всегда работает


Я хотел реализовать функцию MiddleClick-to-Delete, как и большинство окружений с вкладками, в моем приложении, которое выглядит следующим образом:

Введите описание изображения здесь

Это просто одна форма с TabControl, которая имеет 2x TabPage: ActiveItems и архивированные элементы.

Обе эти страницы содержат свои собственные TabControl, которые пользователь может добавить столько TabPage объектов, сколько он пожелает.

Если пользователь выбрал активные элементы и они удаляют вкладку, он удаляет правильную. Если они ... удалите вкладку из архивированных элементов, она также удаляет правильный. Если они перемещают вкладку из активной в архивную, а затем удаляют ее, это удаление неправильной вкладки. Итак, на скриншоте выше вы не можете увидеть архивированные элементы, но там уже есть 2 вкладки. Если я перееду 13571 из Active -> архив, затем удалить его (вкладка #3, индекс #2), он удаляет вкладку #2, показатель #1.

// Both the tcActive and tcArchived, the TabControls on tcRoot's 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);
}

Пошаговое выполнение кода для условия, описанного выше:

  • MouseDown событие пожары
  • DeleteTab()
  • GetTabIndex возвращает 2
  • DeleteTab(tcArchived, 2); называется
  • Tab deletedTab имеет все значения, которые он должен содержать, указывая, что мы смотрим на правильную страницу / индекс.
  • tc.RemoveAt(2) называется

Однако он удаляет второй элемент, а не Индекс 2. Абсолютно не могу понять, что случилось.

1 3

1 ответ:

Изменение этой строки:

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

Кому:

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

Похоже, что это работает для случая использования, описанного в моем оригинальном посте, с минимальным тестированием. Но я быдействительно хотел знать, почему RemoveAt(tabIndex) не работает.