4

I have a WPF usercontrol (myGraphicControl) in a tab (WPF application).

When the form size changes, I redraw the graph in myGraphicControl.

Since the redrawing operation is a I need to do it only the control in in the visible tab.

How the WPF (user)control can detect if it's "visible" actually or not?

PS.

by Visible I mean that user can see it. say, if a Visible TextBox is located in the currently invisible tab, this textBox is not visible by the user.

serhio
  • 28,010
  • 62
  • 221
  • 374
  • What do you mean by visible? On top, not obscured in any way? – Emond Apr 06 '11 at 13:11
  • I had the same problem and I solved it. I wrote the solution in this thread: http://stackoverflow.com/questions/1517743/in-wpf-how-can-i-determine-whether-a-control-is-visible-to-the-user/42254899#42254899 – Ofer Barasofsky Feb 21 '17 at 15:43

3 Answers3

3

I don't believe there is a quick-fix solution here, but you may be able to do something using UIElement.InputHitTest(Point).

You could make a call similar to

//get the coordinates of the top left corner of the child control within
//the parent
var childTopLeft = childControl.TranslatePoint(new Point(), parentControl);
//check whether or not the child control is returned when you request the element
//at that coordinate through hit testing
var isVisible = (parentControl.InputHitTest(childTopLeft) == childControl);

However, I should point out that I haven't tried this myself, and that it probably won't work in the following scenarios:

  • Transparent items - generally, transparent backgrounds cause hit testing of a control to pass to the parent
  • Partially occluded items - you can only hit-test one point at a time, so if only part of your child control is visible you will have to check the correct point
Steve Greatrex
  • 15,789
  • 5
  • 59
  • 73
2

I've found that while Steve's method generally works, it works much more reliably if you get a point from somewhere in the middle of the child control. I'm guessing that maybe layout rounding somewhere along the way makes the InputHitTest check somewhat inexact. So, change his first line to the following and you're golden:

var childTopLeft = childControl.TranslatePoint(new Point(childControl.RenderSize.Width/2, childControl.RenderSize.Height/2), parentControl);
ivanatpr
  • 1,862
  • 14
  • 18
1

Maybe UIElement.IsVisible will be helpful? It works for tab contents well. Anyway you can use a solution described here.

I have one more solution. The current implementation of TabControl removes inactive tabs from visual tree. So, another way to determine whether your element is visible is to find PresentationSource. It will be null for elements of inactive tabs.

Marat Khasanov
  • 3,808
  • 19
  • 22
  • ) let's say, before asking here, testing "IsVisible" is the first thing that can be tested. My element is always IsVisible, that means that is not hidden, but not if the user can see it, because is in the "inactive" tab. – serhio Apr 06 '11 at 13:36
  • Thanks for the second link. Unfortunately my control is not in a Scrollwiever, but in a tab of TabControl. – serhio Apr 06 '11 at 13:39
  • 1
    Ok, I tested it too. And this property was false for elements in "inactive" tab. Maybe you should repeat your test? :) – Marat Khasanov Apr 06 '11 at 13:44
  • I changed my answer to add another solution :) – Marat Khasanov Apr 06 '11 at 13:58
  • the problem is that I use the WindowsForm tab control. I have a WPF UserControl hosted in a Winforms application. So the TabControl is the WinForms one... – serhio Apr 06 '11 at 17:38