Search code examples
xamluwpc++-winrtwinui

How can I tell if a control is actually Visible in UWP?


I'm trying to see if one of my controls is Visible (to put focus on it), but when I check the Visibility property, it is always Visible, even if an ancestor is hidden. How can I tell if a given control is actually visible (even if it's virtualized or off-screen)?

<StackPanel x:Name="StackPanelThatGetsHidden" Visibility="Hidden">
  <Button x:Name="TheButton">Focus me</Button>
</StackPanel>
TheButton().Visibility() // => Visible
TheButton().Focus() // => false, since the button is actually invisible

Solution

  • Unfortunately, there is no easy way to detect if any parent item is hidden (non-Visible). You'll have to loop through the visual tree:

    // NOTE: this does not check a bajillion other properties; a control can still be off-screen,
    // virtualized, etc. This only checks ancestor visibility.
    bool IsControlVisible(winrt::FrameworkElement const& control)
    {
        auto currentElement = control;
        while (currentElement)
        {
            if (currentElement.Visibility() != winrt::Visibility::Visible)
            {
                return false;
            }
            currentElement = winrt::VisualTreeHelper::GetParent(currentElement).try_as<winrt::FrameworkElement>();
        }
    
        return true;
    }
    

    See Proposal: Add a way to track effective visibility of a control, a GitHub issue requesting similar functionality be added to UWP/WinUI.