Page 1 of 1

Any way to know if a UIElement is visible in the window?

Posted: 21 Aug 2019, 21:01
by darthmaule2
I have a ListView bound to an ObservableCollection of 100s of items, each of which has an associated Noesis.BitmapImage that must be displayed as a thumbnail on the screen. I can't load them all at once or the UI thread pauses for a long time. So, I only want to load the ones that are visible in the screen when scrolling stops.

How do I check if a UIElement is visible? (The IsVisible property returns true even for offscreen elements).

I found the below code somewhere but it uses "TransformBounds" which doesn't appear to be implemented in Noesis...
        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, container.ActualWidth, container.ActualHeight);
            return rect.IntersectsWith(bounds);
        }


Thanks.

Re: Any way to know if a UIElement is visible in the window?

Posted: 22 Aug 2019, 20:12
by sfernandez
Is the BitmapImage exposed as a property in each item view model?

Considering a ListView uses virtualization to render the items (so only visible ones are generated in the UI side), you can maybe delay the loading of the images to the first time the Image property is requested:
public class Item
{
  public Noesis.BitmapImage Image
  {
    get
    {
      if (_image == null)
      {
        _image = new Noesis.BitmapImage(_imagePath);
      }
      return _image;
    }
  }
  ...
}
Do you think this could work for you?

Re: Any way to know if a UIElement is visible in the window?

Posted: 26 Oct 2020, 17:43
by riacosta
I'm creating a VirtualizingWrapPanel and I need this function. Is there any work around?

Re: Any way to know if a UIElement is visible in the window?

Posted: 26 Oct 2020, 20:29
by sfernandez
Are you referring to TransformBounds function?
We are deviating from WPF because our TransformToAncestor returns a 4x4 matrix, but you can use the returned matrix to transform a Rect as follows:
Rect bounds = new Rect(0.0, 0.0, element.RenderSize.Width, element.RenderSize.Height);
bounds.Transform(element.TransformToAncestor(container));

Re: Any way to know if a UIElement is visible in the window?

Posted: 27 Oct 2020, 11:30
by sfernandez
Just to make it clear, we don't have TransformBounds implemented, but you can implement it yourself with the aforementioned code:
public static class Matrix4Ext
{
    public static Rect TransformBounds(this Matrix4 matrix, Rect bounds)
    {
        bounds.Transform(matrix);
        return bounds;
    }
}
In the next release we will add it to Matrix4 type so following code will also work in Noesis:
Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.RenderSize.Width, element.RenderSize.Height));