Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Extension Method to make a control visible in a complex hierarchy

0.00/5 (No votes)
25 Dec 2011 1  
Set visibility in complex (or composite) form.

This tip is compliment to the tip at: Extension method to determine if control is visible in complex hierarchy[^].


Consider the scenario where you have multiple nested tabcontrols:


TabControlMain
  TabPageMainOne
    TabControlSubOne
      TabPageSubOne
      TabPageSubTwo
           MyControl
  TabPageMainTwo
    TabControlMoreSubs
      TabPageMoreSubsOne
      TabPageMoreSubsTwo

The common (naive) approach to make MyControl visible on screen is cumbersome and error prone:


C#
// Make my MyControl visible
TabControlSubOne.ActivePage = TabPageSubOne;
TabControlMain.ActivePage = TabPageMainOne;

This kind of works, until the screen is turned into a usercontrol and placed on a third TabControl. Now there is another control to consider, but your code was not designed to do so. This is a common scenario in dynamically composed screens.


Another problem with this method occurs within the screen itself and has to do with maintainability. What happens if we redesign the screen and decide that MyControl should be moved to TabPageMoreSubsTwo? Now the code does not actually show the control, but, because there is a huge 'disconnect' between what we are trying to do and how we are doing it, we might not discover the problem until late.


As stated, the big problem here is the huge difference between what we are trying to do and how we are doing it. What we really need is a method that follows the Parent-hierarchy up to the Form and 'fix' all TabControls (or equivalent) to make the control visible. That is what this extension does.


Usage:


C#
// Make MyControl visible
MyControl.TabSwitchToControl();

This extension method has a nice benefit that we abstract away the 'how', and only the 'what' of the source code remains. +1 For readability.


C#
public static void LogError(this Exception ex)
{
  //TODO: use your prefered error logging mechanism
}

/// <summary>
/// Tries to make your control visible by setting the
/// 'active tab' property (or equivalent) of all tabcontrols
/// (or other container controls) in your form hierarchy. 
/// The method does this in the same order as a user would have to, when using the interface.
/// Supports: TabControl, UltraTabPageControl, UltraExplorerBarContainerControl.
/// </summary>
/// <param name="subjec">The subject.<</param>
/// <param name="shouldActivateControl">True if the control should be activated/selected.</param>
/// <returns>true if subject is assigned, otherwise false.</returns>
public static bool TabSwitchToControl(this Control subject, bool shouldActivateControl = false)
{
    bool result = true;
    if (subject == null)
    {
        result = false;
    }
    else
    {
        List<control> tabSwitches = new List<control>();
        #region Build a list of tabswitched to perform to make the control visible

        var testSubject = subject;
        while (testSubject != null)
        {
            var asTabPage = (testSubject as TabPage);
            if (asTabPage != null)
            {
                var asTabControl = asTabPage.Parent as TabControl;
                if (asTabControl != null)
                {
                    tabSwitches.Insert(0, testSubject);
                    testSubject = asTabControl;
                }
            }
            else
            {
                var asUltraPage = testSubject as UltraTabPageControl;
                if (asUltraPage != null)
                {
                    tabSwitches.Insert(0, testSubject);
                    testSubject = asUltraPage.TabControl;
                }
                else
                {
                    var asGroupContainer = testSubject as UltraExplorerBarContainerControl;
                    if (asGroupContainer != null)
                    {
                        tabSwitches.Insert(0, testSubject);
                        testSubject = asGroupContainer.Parent;
                    }
                }
            }
            // jump up one parent in the hierarchy until the top control is reached.
            if (testSubject != null)
            {
                testSubject = testSubject.Parent;
            }
        }
        #endregion

        //apply the tabswitches in the same order as a user would.
        foreach (Control control in tabSwitches)
        {
            try
            {
                var page = control as UltraTabPageControl;
                if (page != null)
                {
                    page.TabControl.SelectedTab = page.Tab;
                }
                else
                {
                    var asTabPage = control as TabPage;
                    if (asTabPage != null)
                    {
                        var tabControl = asTabPage.Parent as TabControl;
                        tabControl.SelectedTab = asTabPage;
                    }
                    else
                    {
                        var asExplorerContainer =  control as UltraExplorerBarContainerControl;
                        if (asExplorerContainer != null)
                        {
                            var explorerBar = (control.Parent as UltraExplorerBar);
                            var explorerGroup = explorerBar.Groups[control.Name];
                            if (explorerBar.SelectedGroup != explorerGroup)
                            {
                                explorerBar.SelectedGroup = explorerGroup;
                            }
                        }
                    }
                }
            }
            catch (Exception exp)
            {
                // Catch exceptions to prevent application termination because of 
                // a bad event handler. For example a refresh of a control failed 
                // because the internet connection was dropped.
                exp.LogError();
                result = false;
            }
        }
        if (shouldActivateControl)
        {
            subject.Select(); 
        }
    }
    return result;
}


(Edit: Fixed some typos)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here