5
votes

We have a very large child control which does a lot of rendering to display its detail, but since only a portion of that control is actually visible (it's clipped by something further up the hierarchy, not necessarily its immediate parent) we only want to render the visible portion during the OnRender call.

Consider the following picture. The child is 100x50 but the visible area is a rectangle with corners at (10,5) and (100,50) in child coordinates. That's the area we're looking for.

Clipped Child

Note: You can't simply do coordinate conversions from the child to the parent and test for clipping because it may not be the parent that's doing the clipping.

Consider nested Canvas controls inside a ScrollViewer. The inner Canvas may very well lay completely within the bounds of the outer Canvas, but the outer Canvas may be clipped by the ScrollViewer, thus the inner Canvas is visually clipped by it as well.

Walking the visual tree and testing each parent would kill performance.

So is there anything built in to WPF that can get the bounds of the visible area of a control?

1
This thread might help you get what you want: stackoverflow.com/questions/1517743/…JimSt24
Nope! That's just bounds-checking (see my 'note' above.) That doesn't actually represent what's visible.Mark A. Donohoe
Just a stab in the dark - use reflector to look into the internals of IsMouseDirectlyOver property (found on most WPF controls, probably inherited from FrameworkElement). That property looks through nested objects to determine whether the mouse is directly over the exact specific control. I'm thinking that you might be able to use similar logic for bounds checking...Marko

1 Answers

0
votes

I would suggest that, in general, within your OnRender method you should compose or render your visible items with careful attention to their Z-order, but not necessarily spend time worrying about what's visible. This is not C++. Part of the reasoning behind the design of WPF is that the system should be able to decide for you, what is visible and what is not. It's intended to be a somewhat higher level of abstraction. If you find that you're writing code to test for what is visible, and what the bounds are of that visible portion -- you're probably not using it correctly. Be.. a bit lazier. This (what you described above) is supposed to be quite simple.

As your visible objects slide around, or move about in verticle order (ie, Z-order) -- they will simply become visible, or not. If you want something to be not-visible despite it's position within the Z-order, then you make it invisible (ideally, by binding it to a property that evaluates to Visibility.Visible, Visibility.Hidden, or Visibility.Collapsed).

Also note: when looking at various implementations of graphics -- especially for developers coming to WPF from other platforms, I often find that there was actually no need to override OnRender. Unless you have a lot of graphics that has to be rendered in realtime, you can often let WPF do the work for you and just define what you want to display within your XAML.