2

I have a TabControl to which the user can add/remove TabPages using two user buttons. To get a clear idea, the GUI looks like this:

enter image description here

If the user clicks on the "Plus" icon (the Parent being the main form which is also the Parent of the TabControl itself), a new TabPage containing a custom user control gets added:

TabPage indicator = new TabPage();
indicator.Controls.Add(new IndicatorTab(this.conditionsTab, this.limitsTab) { Dock = DockStyle.Fill});
indicatorsTab.TabPages.Add(indicator);

If the user clicks on the "Remove" button inside the User Control, the following occurs:

Parent.Dispose();

I have added an ControlEventHandler to this TabControl for the events ControlAdded and ControlRemoved, in which I run this loop:

foreach (TabPage indicator in indicatorsTab.TabPages)
{
    //stuff
}

My problem is the following:

  • When the ControlAdded event is triggered, I find in indicatorsTab.TabPages all the TabPage including the one just added - EXPECTED TO ME
  • When the ControlRemoved event is triggered, I find in indicatorsTab.TabPages all the TabPage including the one just removed - UNEXPECTED TO ME

I wouldn't expect the removed tab to be in indicatorsTab.TabPages after the ControlRemoved was triggered. So I have a couple of questions:

  1. Am I being wrong in my logic? Is it expected the removed TabPageto be still in the collection right after the event is triggered?
  2. How can I get the refreshed list of TabPages after the removal event?
  3. Don't know why but I get the feeling this diverging behavior has something to see with the fact that the ControlAdded event is triggered by a "brother" control (child of the same Parent than the TabControl), while the ControlRemoved is triggered by a child of the TabControl itself... if so, can anyone please explain?
Matteo NNZ
  • 11,930
  • 12
  • 52
  • 89
  • The `TabPages` collection has not been updated, yet. It will be, after the `ControlRemoved` event. You could use the `indicatorsTab.Controls` collection in the loop: `foreach (TabPage indicator in indicatorsTab.Controls) (...)`. Or check the `e.Control` object (the Control just removed) and skip it in the loop (using its `Name`, maybe, to identify it). – Jimi Feb 05 '19 at 02:02

1 Answers1

2

You can delay the eventhandler execution until after the remove is processed:

private void tabControl1_ControlRemoved(object sender, ControlEventArgs e)
{
    BeginInvoke(new Action(() =>
    {
        MessageBox.Show(tabControl1.TabCount.ToString());
    }));
}

It shows the expected result.

Note: TabControl has its own ControlsCollection class and in its Remove method, it first removes the TabPage control from Controls collection and raises ControlRemoved, then removes the TabPage from TabPages collection. So as a result, in the ControlRemoved event, the TabPage still exists in TabPages collection, but not in Controls collection.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    Thank you, will try this later and accept the answer if it works! – Matteo NNZ Feb 05 '19 at 13:12
  • It works exactly the way I wanted it, thank you very much! Still, it would be interesting to know why the `ControlAdded` takes the new `TabPage` into account while the `ControlRemoved` doesn't, but that's of secondary importance now :) – Matteo NNZ Feb 05 '19 at 20:30
  • 1
    @MatteoNNZ You're welcome. Updated the answer to contain some information about how removing tab pages works in tab control. Take a look at source code of [`Remove`](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/TabControl.cs,6cba8857b84046b6) method for better understanding. – Reza Aghaei Feb 05 '19 at 21:36
  • 2
    @MatteoNNZ If you take a look at the source code, you'll clearly see that the [Add method](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/TabControl.cs,2733) first adds the `TabPage` to the collection, then calls `base.Add(tabPage)`. The opposite in the `Remove` method. – Jimi Feb 06 '19 at 11:55
  • @Jimi interesting catch, if you write it as an answer I will at least upvote it as it responds to one of my "lower priority" questions :) – Matteo NNZ Feb 06 '19 at 12:09
  • @MatteoNNZ As an off-topic note, regarding to the UI that I see in your question, you may be interested to a [TabControl with Close and Add Button](https://stackoverflow.com/a/36900582/3110834). – Reza Aghaei Feb 06 '19 at 12:23
  • @RezaAghaei oh, that's a pity, I've already implemented everything! But I've added your approach to my favorites for the next time I'll have to do it! – Matteo NNZ Feb 06 '19 at 13:06