Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Extension method to determine if control is visible in complex hierarchy

5.00/5 (1 vote)
25 Dec 2011CPOL1 min read 24.4K  
Determine visibility in complex (or composite) form
This tip is compliment to the tip at: Extension method to make a control 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 determining whether MyControl is currently visible on screen is either cumbersome or error prone:

C#
// See if MyControl is visible, if it is, I should refresh it.
bool isVisible = 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 our test is invalid, but because the code itself is not obviously wrong, we might not discover the problem until it is too late (production).

So obviously, this is less than desirable. What went wrong?
Let's return to the original problem and the way it is implemented. The question asked was 'Is My Control Visible' but it was implemented as: 'Have some tabcontrols the correct active page property'. The problem with the implementation is the word 'some' as I have shown above that checking 'some' might not be enough, or even be the wrong ones.

To solve the problem, we should implement this as 'Have ALL tabcontrols the correct active page property'? which is what this extension method does.

Usage:
C#
// See if MyControl is visible, if it is, I should refresh it.
bool isVisible = MyControl.IsMyControlVisible();


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#
/// <summary>
/// Checks to see whether the provided subject is visible in the tabpage hierarchy of a form.
/// It navigates up the parent-hierarchy and when it encounters a tabControl, checks to see whether
/// the current parent is actually the active tabpage. When the result of this check is false, 
/// the functions exits with false as a result.
/// Supports TabControls and Infragistics.UltraTabPageControl
/// </summary>
/// <param name="subject">The subject.</param>
/// <returns>
/// True is all tabpages where the active control.
/// </returns>
public static bool IsMyControlVisible(this Control subject)
{
    if ((subject == null) || (subject.Parent == null))
    {
      return false;
    }
	 
    Control testSubject = subject;
    TabControl parentPageControl = null;
    UltraTabPageControl aPage = null;
    Control testSubject = subject;
    while (testSubject != null)
    {
        TabPage asTabPage = (testSubject as TabPage);
        if (asTabPage == null)
        {
            UltraTabPageControl asUltraTabPage = testSubject as UltraTabPageControl;
            if (asUltraTabPage != null)
            {
                if (asUltraTabPage.TabControl == null)
                {
                    return false;
                }
                if (asUltraTabPage.TabControl.SelectedTab != asUltraTabPage.Tab)
                {
                    return false;
                }
            }
        }
        else
        {
            TabControl parentPageControl = asTabPage.Parent as TabControl;
            if (parentPageControl == null)
            {
                return false;
            }
            if (parentPageControl.SelectedTab != testSubject)
            {
                return false;
            }
            testSubject = parentPageControl;
        }

        if (testSubject != null)
        {
            testSubject = testSubject.Parent;
        }
    }
    return true;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)