代码之家  ›  专栏  ›  技术社区  ›  sab669

用于删除嵌套TabPage的代码并不总是有效的

  •  3
  • sab669  · 技术社区  · 9 年前

    我想在我的应用程序上实现MiddleClick to Delete功能,就像大多数选项卡式环境一样,如下所示:

    enter image description here

    这只是一个带有 TabControl 有2倍 TabPage :ActiveItems和Archived Items。

    这两个页面都包含自己的 选项卡控件 ,用户可以添加任意数量的 选项卡页 如他们所愿。

    如果用户选择了“活动项”并删除了某个选项卡,则会删除正确的选项卡。如果他们从存档项目中删除了一个选项卡,它也会删除正确的选项卡。如果他们将一个选项卡从“活动”移动到“已存档”,然后删除它,这意味着删除了错误的选项卡。因此,在上面的屏幕截图中,您无法看到“已存档项目”,但已经有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 具有它应该包含的所有值,表明我们正在查看正确的TabPage/index。
    • tc.RemoveAt(2) 被调用

    然而,它删除了第二项,而不是索引2。绝对无法找出问题所在。

    1 回复  |  直到 4 年前
        1
  •  4
  •   sab669    9 年前

    更改此行:

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

    收件人:

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

    看起来它适用于我最初文章中描述的用例,只需要很少的测试。但我会 真正地 想知道为什么 RemoveAt(tabIndex) 不起作用。