Ví dụ có UserControl như sau:
-->
<UserControl x:Class="TestHitTest.DemoControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="200">
<Grid>
<Label Content="This is a demo control" />
<Rectangle Fill="#FF1E59C1" Stroke="Black" HorizontalAlignment="Left" Margin="18,18,0,0" VerticalAlignment="Top" Width="93" Height="48" Opacity="0.7"/>
<Rectangle Fill="#FF83A3DA" Stroke="Black" Margin="71,29,80,0" VerticalAlignment="Top" Height="56" Opacity="0.7"/>
<Rectangle Fill="#FF2D3441" Stroke="Black" HorizontalAlignment="Left" Margin="53,47,0,0" VerticalAlignment="Top" Width="48" Height="38" Opacity="0.7"/>
<Rectangle Fill="#FF97A2B5" Stroke="Black" HorizontalAlignment="Left" Margin="18,75,0,0" VerticalAlignment="Top" Width="53" Height="53" Opacity="0.7"/>
<Rectangle Fill="#FF7AA4EE" Stroke="Black" HorizontalAlignment="Left" Margin="32,96,0,114" Width="55" Opacity="0.7"/>
<Rectangle Fill="#FF3E547A" Stroke="Black" HorizontalAlignment="Right" Margin="0,56,31,0" VerticalAlignment="Top" Width="102" Height="56" Opacity="0.7"/>
Grid>
UserControl>
|
-->
<Window x:Class="TestHitTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestHitTest" Title="Window1" Width="600" Height="300">
<Grid x:Name="_grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
Grid.ColumnDefinitions>
<local:DemoControl x:Name="_leftControl" Grid.Column="0" />
<local:DemoControl x:Name="_rightControl" Grid.Column="1" />
Grid>
Window>
|
Dạng như sau:
Bây giờ đơn giản khi click chúng ta cần xác định click vào user control bên phải hay bên trái và chúng ta đang đề cập VisualTreeHelper.HitTest.
Test thử HitTest
-->
namespace TestHitTest
{
///
/// Interaction logic for Window1.xaml
///
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
}
void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pt = e.GetPosition(_grid);
var area = new EllipseGeometry(pt, 1, 1);
Debug.WriteLine("--- Demo hit test ---");
VisualTreeHelper.HitTest(
_grid,
filter =>
{
Debug.WriteLine("Pass through filter " + filter);
return HitTestFilterBehavior.Continue;
},
result =>
{
Debug.WriteLine("Pass through result " + result.VisualHit);
return HitTestResultBehavior.Continue;
},
new GeometryHitTestParameters(area)
);
}
}
}
|
--- Demo hit test --- Pass through filter System.Windows.Controls.Grid Pass through filter TestHitTest.DemoControl Pass through filter System.Windows.Controls.Border Pass through filter System.Windows.Controls.ContentPresenter Pass through filter System.Windows.Controls.Grid Pass through filter System.Windows.Shapes.Rectangle Pass through result System.Windows.Shapes.Rectangle Pass through filter System.Windows.Shapes.Rectangle Pass through result System.Windows.Shapes.Rectangle Pass through filter System.Windows.Shapes.Rectangle Pass through result System.Windows.Shapes.Rectangle Pass through filter System.Windows.Controls.Label: This is a demo control Pass through filter System.Windows.Controls.Border Pass through result System.Windows.Controls.Border |
void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pt = e.GetPosition(_grid);
var area = new EllipseGeometry(pt, 1, 1);
Debug.WriteLine("--- Demo hit test ---");
VisualTreeHelper.HitTest(
_grid,
filter =>
{
Debug.WriteLine("Pass through filter " + filter);
if (filter.GetType().IsAssignableFrom(typeof(DemoControl)))
{
return HitTestFilterBehavior.ContinueSkipChildren;
}
else
{
return HitTestFilterBehavior.Continue;
}
},
result =>
{
Debug.WriteLine("Pass through result " + result.VisualHit);
return HitTestResultBehavior.Continue;
},
new GeometryHitTestParameters(area)
);
}
|
--- Demo hit test --- Pass through filter System.Windows.Controls.Grid Pass through filter TestHitTest.DemoControl |
Chúng ta sẽ thực hiện tìm parent cho hit test result
public static T FindVisualParent<T>(DependencyObject child)
where T : DependencyObject
{
// get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
// we’ve reached the end of the tree
if (parentObject == null) return null;
// check if the parent matches the type we’re looking for
T parent = parentObject as T;
if (parent != null)
{
return parent;
}
else
{
// use recursion to proceed with next level
return FindVisualParent<T>(parentObject);
}
}
|
void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pt = e.GetPosition(_grid);
var area = new EllipseGeometry(pt, 1, 1);
bool isLeft = false;
bool isRight = false;
Debug.WriteLine("--- Demo hit test ---");
VisualTreeHelper.HitTest(
_grid,
null,
result =>
{
Debug.WriteLine("Pass through result " + result.VisualHit);
IntersectionDetail detail = ((GeometryHitTestResult)result).IntersectionDetail;
switch (detail)
{
case IntersectionDetail.FullyContains:
case IntersectionDetail.Intersects:
case IntersectionDetail.FullyInside:
Debug.WriteLine(result.VisualHit.ToString());
DemoControl control = FindVisualParent<DemoControl>(result.VisualHit);
if (control != null)
{
if (control.Equals(_leftControl))
{
isLeft = true;
Debug.WriteLine("Click on left control");
}
else if (control.Equals(_rightControl))
{
isRight = true;
Debug.WriteLine("Click on right control");
}
return HitTestResultBehavior.Stop;
}
return HitTestResultBehavior.Continue;
default:
return HitTestResultBehavior.Stop;
}
},
new GeometryHitTestParameters(area)
);
}
|