问题
I have a form in my application with a tab control containing two tabs. in one of the tabs I have a UIElement. When mouse hover on it a timer is started, and after a second some functionality is performed.
The problem is when hovering with the mouse and immediately switching tab, than I need to stop the timer. doing it in the tab control events is not possible to me (the tab control does not recognize the timer). I want to be able to know when this UIElement is not visible on screen (Visibility property is still Visible when switching tabs).
This is how it looked:
private void element_MouseEnter(object sender, MouseEventArgs e)
{
timer.Start()
}
private void dt_Tick(object sender, EventArgs e)
{
//Some functionality
}
回答1:
AFAIK, there is no reliable way to test if the element is visible or not.
In Silverlight, there are too many ways why an element can be hidden (outside of the screen, obscure by ScrollViewer, overlap by another element, make completely transparent, distort by a shader effect, etc.) and unhidden (specify Z-order, specify custom render transform, overlap by inverse effect, etc.)
Here are two workarounds that may or may not fit your requirements:
If you’re trying to do something similar to tooltip, add handler to MouseLeave event for your UIElement. In that event, if the timer is active, stop it.
Alternatively, inside dt_Tick handler you can check which tab is shown by checking the
TabControl.SelectedIndex
property, if the wrong one is selected just ignore this event.
Update: here's some sample code (untested) for the #2:
public static IEnumerable<FrameworkElement> visualParents( this FrameworkElement e )
{
DependencyObject obj = e;
while( true )
{
obj = VisualTreeHelper.GetParent( obj );
if( null == obj ) yield break;
FrameworkElement fwe = obj as FrameworkElement;
if( null != fwe ) yield return fwe;
}
}
public static bool isOnVisibleTab( FrameworkElement elt )
{
TabItem item = elt.visualParents().OfType<TabItem>().FirstOrDefault();
if( null == item )
return true; // Did not find the tab, return true
return item.IsSelected; // Found the tab, return true if the tab is selected
}
回答2:
You can solve this with the Unloaded
event. It is raised whenever changes to the VisualTree happen that result in the Element being part of a VisualTree branch that is not currently rendered.
private void element_MouseEnter(object sender, MouseEventArgs e)
{
timer.Start();
element.Unloaded += OnElementUnloaded;
}
private void OnElementUnloaded(object sender, EventArgs e)
{
element.Unloaded -= OnElementUnloaded;
timer.Stop();
}
private void dt_Tick(object sender, EventArgs e)
{
element.Unloaded -= OnElementUnloaded;
//Some functionality
}
来源:https://stackoverflow.com/questions/21658042/silverlight-determine-if-a-uielement-is-visible-on-screen