给定一个相对于Page的点,我如何针对TabControl的选项卡进行测试? VisualTreeHelper.HitTest
给了我内容,但是当我走上视觉树时,我看不到任何可以告诉我实际上已经碰到标签的东西。我甚至看不到标签控件本身。
public class ViewManipulationAgent : IDisposable
{
private const int _limit = 125;
private INavigationService _navigationService;
private FrameworkElement _container;
private FrameworkElement _element;
private TranslateTransform _translate;
private IInputElement _touchTarget;
// When I use this object,
// a_container is the main Frame control in my application.
// a_element is a page within that frame.
public ViewManipulationAgent(FrameworkElement a_container, FrameworkElement a_element)
{
_navigationService = a_navigationService;
_container = a_container;
_element = a_element;
// Since I set IsManipulationEnabled to true all touch commands are suspended
// for all commands on the page (a_element) unless I specifically cancel (see below)
_element.IsManipulationEnabled = true;
_element.PreviewTouchDown += OnElementPreviewTouchDown;
_element.ManipulationStarting += OnElementManipulationStarting;
_element.ManipulationDelta += OnElementManipulationDelta;
_element.ManipulationCompleted += OnElementManipulationCompleted;
_translate = new TranslateTransform(0.0, 0.0);
_element.RenderTransform = _translate;
}
// Since the ManipulationStarting doesn't provide position I capture the position
// here and then hit test elements to find any controls for which I want to bypass
// manipulation.
private void OnElementPreviewTouchDown(object sender, TouchEventArgs e)
{
var position = e.GetTouchPoint(_element).Position;
_touchTarget = null;
HitTestResult result = VisualTreeHelper.HitTest(_element, position);
if (result.VisualHit == null)
return;
var button = VisualTreeHelperEx.FindAncestorByType<ButtonBase>(result.VisualHit) as ButtonBase;
if (button != null)
{
_touchTarget = button;
return;
}
var slider = VisualTreeHelperEx.FindAncestorByType<Slider>(result.VisualHit) as Slider;
if (slider != null)
{
_touchTarget = slider;
return;
}
}
// Here is where I cancel manipulation if a specific touch target was found in the
// above event.
private void OnElementManipulationStarting(object sender, ManipulationStartingEventArgs e)
{
if (_touchTarget != null)
{
e.Cancel(); // <- I have to cancel manipulation or the buttons and other
// controls cannot be manipulated by the touch interface.
return;
}
e.ManipulationContainer = _container;
}
private void OnElementManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
var element = e.Source as FrameworkElement;
if (element == null)
return;
var translate = _translate.X + e.DeltaManipulation.Translation.X;
if (translate > _limit)
{
GoBack();
translate = _limit;
}
if (translate < -_limit)
{
GoForward();
translate = -_limit;
}
_translate.X = translate;
}
private void GoForward()
{
var navigationService = ServiceLocator.Current.GetInstance<INavigationService>();
navigationService.GoForward();
}
private void GoBack()
{
var navigationService = ServiceLocator.Current.GetInstance<INavigationService>();
navigationService.GoBack();
}
private void OnElementManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
_touchTarget = null;
_translate.X = 0;
}
public void Dispose()
{
_element.PreviewTouchDown -= OnElementPreviewTouchDown;
_element.ManipulationStarting -= OnElementManipulationStarting;
_element.ManipulationDelta -= OnElementManipulationDelta;
_element.ManipulationCompleted -= OnElementManipulationCompleted;
}
}