Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In WPF, how can I determine whether a control is visible to the user?

I'm displaying a very big tree with a lot of items in it. Each of these items shows information to the user through its associated UserControl control, and this information has to be updated every 250 milliseconds, which can be a very expensive task since I'm also using reflection to access to some of their values. My first approach was to use the IsVisible property, but it doesn't work as I expected.

Is there any way I could determine whether a control is 'visible' to the user?

Note: I'm already using the IsExpanded property to skip updating collapsed nodes, but some nodes have 100+ elements and can't find a way to skip those which are outside the grid viewport.

like image 265
Trap Avatar asked Oct 04 '09 23:10

Trap


People also ask

How can I find WPF controls by Name or type?

FindName method of FrameworkElement class is used to find elements or controls by their Name properties. This article shows how to find controls on a Window by name. FindName method of FrameworkElement class is used to find elements or controls by their Name properties.

What is user control WPF?

User controls, in WPF represented by the UserControl class, is the concept of grouping markup and code into a reusable container, so that the same interface, with the same functionality, can be used in several different places and even across several applications.


2 Answers

You can use this little helper function I just wrote that will check if an element is visible for the user, in a given container. The function returns true if the element is partly visible. If you want to check if it's fully visible, replace the last line by rect.Contains(bounds).

private bool IsUserVisible(FrameworkElement element, FrameworkElement container) {     if (!element.IsVisible)         return false;      Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));     Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);     return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight); } 

In your case, element will be your user control, and container your Window.

like image 59
Julien Lebosquain Avatar answered Sep 21 '22 09:09

Julien Lebosquain


public static bool IsUserVisible(this UIElement element) {     if (!element.IsVisible)         return false;     var container = VisualTreeHelper.GetParent(element) as FrameworkElement;     if (container == null) throw new ArgumentNullException("container");      Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.RenderSize.Width, element.RenderSize.Height));     Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);     return rect.IntersectsWith(bounds); } 
like image 39
Andreas Avatar answered Sep 19 '22 09:09

Andreas