3
\$\begingroup\$

I order to speed up opening of a file (which contents are displayed in a series of tabs), I made it so that tab content is generated only when the user first clicks on the tab. If user never opens the tab, code never executes.

The problem is I could not any find any TabPage events that would trigger when that tab is selected. I had to use SelectedIndexChanged event from the TabControl.

In order to make it work, I created a new interface (ICreateTab) that every TabPage implemented. It only has CreateTab() method which would contain the code that would generate data for the TabPage.

This is the snippet of the code:

    TabControl tabs;
    bool[] tabCreated;

    public ConstructorForClassThatHasTabControl()
    {
        tabs = new TabControl();
        tabs.Controls.Add(new TabPageWithImplementedICreateTabInterface1());
        .
        .
        .
        tabs.Controls.Add(new TabPageWithImplementedICreateTabInterfaceN());

        tabs.SelectedIndexChanged += OnSelectedIndexChanged;

        tabCreated = new bool[tabs.TabCount];

        // Create first tab, since the event won't be initially triggered
        ((ICreateTab)tabs.Controls[0]).CreateTab();
        tabCreated[0] = true;

        Controls.Add(tabs);
    }

    private void OnSelectedIndexChanged(object sender, EventArgs e)
    {
        if (!tabCreated[tabs.SelectedIndex])
        {
            tabCreated[tabs.SelectedIndex] = true;
            ((ICreateTab)tabs.SelectedTab).CreateTab();
        }
    }

This looks very ugly and messy to me. I'd rather each TabPage have an event that would create it's contents and remove itself so it's not triggered again. I need to avoid dragging TabControl into this matter.

Does TabPage have an event that is triggered when the TabPage is selected? Even if it doesn't, is there a proper way of doing this? I find it hard to believe that TabPage does not know when it's selected.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I don't think there is any other way to solve it. By using the SelectedIndexChanged event and initializing a TabPage you do it just the way it should/can be done.

You may however consider renaming the interface to IInitializable and the method to Initialize which more clearly describes what you are doing. You don't create any tabs, you initialize them so name the interface and the method accordingly.

Internally you can use a boolean field _isInitialized so that the Initialize method checks it and doesn't initialize your tab-page multiple times. Then you just do:

private void OnSelectedIndexChanged(object sender, EventArgs e)
{
    var initializableTabPage = (sender as TabControl).SelectedTab as IInitializable;

    // In case you have other tab-pages.
    if (initializableTabPage != null)
    {
        initializableTabPage.Initialize();
    }        
}

and the tap-page with its interface:

interface IInitializable
{
    void Initialize();
}

class MyTabPage : TabPage, IInitializable
{
    private bool _isInitialized;

    public void Initialize() 
    {
        if (_isInitialized) { return ; }

        ...initialize

        _isInitialized = true;
    }
}

I find it hard to believe that TabPage does not know when it's selected. It looks like it really doesn't: TabPage Class Events

You could experimet with GotFocus but it can be tricky. I wouldn't

\$\endgroup\$
1
  • \$\begingroup\$ GotFocus didn't trigger. It seems that TabPage is actually the panel that displays when you select the tab. The bookmark above seems to be part of TabControl, hence it's not really connected to TabPage. But this does seem like a oversight from Microsoft, no? \$\endgroup\$ Sep 12, 2016 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.