Search code examples
c#winformstabcontrol

Insert existing tab from collection into tabcontrol from another form


I'm new to C# and am building an app to interact with data in a number of ways. I want to offer the user the chance to customise the interface by showing and hiding tabs in a TabControl on the main form (frmTabControl).

So I have added a second form which will be my settings dialog (frmSettings).

On this settings form I have a checkbox to represent each tab in the TabControl.

What I am trying to do is when the settings dialog closes, the tabcontrol gets updated to only show the tabs that have the corresponding check box checked.

So far I have got the "FormClosed" event of the settings form to remove any tabs that have the checkboxes unchecked. But my issues is adding them back in.

So in my main form (frmTabControl), I have a TabControl with 4 pages: tabPage1, tabPage2, tabPage3 and tabPage4

I have this code at the top of the form code:

public partial class frmTabControl : Form
{
  public static frmTabControl frmTBInstance;
  public TabControl tabC;

  public frmTabControl()
  {
    InitializeComponent();
    frmTBInstance = this;
    tabC = tabControl1;
  }

// etc etc 

Then in my setting dialog (frmSettings), I have a checkbox to represent each tab page: chkShowTabPage1, chkShowTabPage2, chkShowTabPage3, chkShowTabPage4

I then have this code inside the FormClosed event of the frmSettings form.

if (chkShowTabPage1.Checked && !frmTabControl.frmTBInstance.tabC.TabPages.ContainsKey("tabPage1"))
{
  frmTabControl.frmTBInstance.tabC.TabPages.Insert(0, tabPage1);
}
else if (!chkShowTabPage1.Checked && frmTabControl.frmTBInstance.tabC.TabPages.ContainsKey("tabPage1"))
{
  frmTabControl.frmTBInstance.tabC.TabPages.RemoveByKey("tabPage1");
}

// repeats for the other 3 check boxes

However, tabPage1 in the if part of the if else code block doesn't recognise the tabPage1 name, it shows an issue stating that "tabPage1 does not exist in this context". The else if part of the if else code block works fine and removes the tab as expected.

So I guess my question is can you not access existing tab pages by their Name property in this way?

If I put a button on the main frmTabControl and have it execute this code:

if (!tabControl1.TabPages.Contains(tabPage1))
  tabControl1.TabPages.Insert(0, tabPage1);
else
  tabControl1.TabPages.Remove(tabPage1);

It toggles the first tab off and on. So the issue only appears to be when I'm accessing the tabcontrol from another form.

I can add a "new" tab page in by putting tabPage1 in quotes i.e. frmTabControl.frmTBInstance.tabC.TabPages.Insert(2, "tabPage1"); but that's not what I need (I need it to add back in the already existing tab page).

Have I created the instance of the tabcontrol incorrectly in the frmSettings form?

I'm still new to C# so a bit lost, and have been trying for hours to find a solution to this, and this is the nearest I have go to getting it to work.


Solution

  • I don't know what the exact issue is with your code. I assume that it is a compilation error. The error message contains a file name and a line number. Carefully look at this line of code. It should also have red squiggly lines where the error is.

    Here is a working solution.

    Note that in the properties window of a control, in the section "Design", you can set Modifier to Public. I made this for the TabControl in frmTabControl. Like this, it can be accessed from the other form.

    I added a parameter to the constructor of frmSettings where an instance of frmTabControl can be passed and also initialized an array of CheckBoxes to enable processing them in a loop:

    private readonly frmTabControl _frmTabControl;
    private readonly CheckBox[] _chkBoxes;
    
    public frmSettings(frmTabControl frmTabControl)
    {
        _frmTabControl = frmTabControl;
        InitializeComponent();
        _chkBoxes = new CheckBox[] { checkBox1, checkBox2, checkBox3, checkBox4, checkBox5 };
        InitializeCheckBoxes();   // See my last code snippet.
    }
    

    FormClosed looks like this:

    private void FrmSettings_FormClosed(object sender, FormClosedEventArgs e)
    {
        for (int i = 0; i < _chkBoxes.Length; i++) {
            string tabKey = "tabPage" + (i + 1);
            bool containsTab = _frmTabControl.tabControl1.TabPages.ContainsKey(tabKey);
            if (_chkBoxes[i].Checked) {
                if (!containsTab) {
                    _frmTabControl.tabControl1.TabPages.Add(tabControl1.TabPages[tabKey]);
                }
            } else {
                if (containsTab) {
                    _frmTabControl.tabControl1.TabPages.RemoveByKey(tabKey);
                }
            }
        }
    }
    

    In frmTabControl I have a button with this Click event handler:

    private void BtnConfigureTabs_Click(object sender, EventArgs e)
    {
        var frm = new frmSettings(this);
        frm.ShowDialog();
    }
    

    These variables are not required anymore:

    public static frmTabControl frmTBInstance;
    public TabControl tabC;
    

    You can also initialize the CheckBoxes to reflect the current status of the pages on frmTabControl:

    private void InitializeCheckBoxes()
    {
        for (int i = 0; i < _chkBoxes.Length; i++) {
            string tabKey = "tabPage" + (i + 1);
            _chkBoxes[i].Checked = _frmTabControl.tabControl1.TabPages.ContainsKey(tabKey);
        }
    }
    

    You would call this in the constructor of frmSettings.