Note that there are some explanatory texts on larger screens.

plurals
  1. POWPF UserControl HitTest
    primarykey
    data
    text
    <p>I have the following user control: a dot and its name: </p> <pre><code>&lt;UserControl x:Class="ShapeTester.StopPoint" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="25" d:DesignWidth="100"&gt; &lt;StackPanel&gt; &lt;Ellipse Stroke="DarkBlue" Fill="LightBlue" Height="10" Width="10"/&gt; &lt;TextBlock Text="Eiffel Tower"/&gt; &lt;/StackPanel&gt; &lt;/UserControl&gt; </code></pre> <p>This is cool. </p> <p>Now, I have a panel, in witch I need to recuperate my StopPoints that I hit with the Mouse: </p> <pre><code>public partial class StopsPanel : UserControl { private List&lt;StopPoint&gt; hitList = new List&lt;StopPoint&gt;(); private EllipseGeometry hitArea = new EllipseGeometry(); public StopsPanel() { InitializeComponent(); Initialize(); } private void Initialize() { foreach (StopPoint point in StopsCanvas.Children) { point.Background = Brushes.LightBlue; } } private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // Initialization: Initialize(); // Get mouse click point: Point pt = e.GetPosition(StopsCanvas); // Define hit-testing area: hitArea = new EllipseGeometry(pt, 1.0, 1.0); hitList.Clear(); // Call HitTest method: VisualTreeHelper.HitTest(StopsCanvas, null, new HitTestResultCallback(HitTestCallback), new GeometryHitTestParameters(hitArea)); if (hitList.Count &gt; 0) { foreach (StopPoint point in hitList) { // Change rectangle fill color if it is hit: point.Background = Brushes.LightCoral; } MessageBox.Show(string.Format( "You hit {0} StopPoint(s)", hitList.Count)); } } public HitTestResultBehavior HitTestCallback(HitTestResult result) { if (result.VisualHit is StopPoint) { // //-------- NEVER ENTER HERE!!! :( // // Retrieve the results of the hit test. IntersectionDetail intersectionDetail = ((GeometryHitTestResult)result).IntersectionDetail; switch (intersectionDetail) { case IntersectionDetail.FullyContains: // Add the hit test result to the list: hitList.Add((StopPoint)result.VisualHit); return HitTestResultBehavior.Continue; case IntersectionDetail.Intersects: // Set the behavior to return visuals at all z-order levels: return HitTestResultBehavior.Continue; case IntersectionDetail.FullyInside: // Set the behavior to return visuals at all z-order levels: return HitTestResultBehavior.Continue; default: return HitTestResultBehavior.Stop; } } else { return HitTestResultBehavior.Continue; } } } </code></pre> <p>So, as you can see, the problem that <strong>the HitTest never identifies an UserControl(StopPoint) as it is, but rather its components</strong>(<em>TextBlock</em>, <em>Ellipse</em> or even <em>Border</em>).<br> As I associate the business object to the StopPoint element, I need to obtain it when MouseHitting, and not its composing elements.</p> <p>Is there a way to do it?</p> <p>EDIT: </p> <p>Using filter (now, it does not enter at all in the HitTestCallback): </p> <pre><code>using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace ShapeTester { /// &lt;summary&gt; /// Interaction logic for StopsPanel.xaml /// &lt;/summary&gt; public partial class StopsPanel : UserControl { private List&lt;StopPoint&gt; hitList = new List&lt;StopPoint&gt;(); private EllipseGeometry hitArea = new EllipseGeometry(); public StopsPanel() { InitializeComponent(); Initialize(); } private void Initialize() { foreach (StopPoint point in StopsCanvas.Children) { point.Background = Brushes.LightBlue; } } private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // Initialization: Initialize(); // Get mouse click point: Point pt = e.GetPosition(StopsCanvas); // Define hit-testing area: hitArea = new EllipseGeometry(pt, 1.0, 1.0); hitList.Clear(); // Call HitTest method: VisualTreeHelper.HitTest(StopsCanvas, new HitTestFilterCallback(MyHitTestFilter), new HitTestResultCallback(HitTestCallback), new GeometryHitTestParameters(hitArea)); if (hitList.Count &gt; 0) { foreach (StopPoint point in hitList) { // Change rectangle fill color if it is hit: point.Background = Brushes.LightCoral; } MessageBox.Show(string.Format( "You hit {0} StopPoint(s)", hitList.Count)); } } public HitTestResultBehavior HitTestCallback(HitTestResult result) { if (result.VisualHit is StopPoint) { // //-------- NEVER ENTER HERE!!! :( // // Retrieve the results of the hit test. IntersectionDetail intersectionDetail = ((GeometryHitTestResult)result).IntersectionDetail; switch (intersectionDetail) { case IntersectionDetail.FullyContains: // Add the hit test result to the list: hitList.Add((StopPoint)result.VisualHit); return HitTestResultBehavior.Continue; case IntersectionDetail.Intersects: // Set the behavior to return visuals at all z-order levels: return HitTestResultBehavior.Continue; case IntersectionDetail.FullyInside: // Set the behavior to return visuals at all z-order levels: return HitTestResultBehavior.Continue; default: return HitTestResultBehavior.Stop; } } else { return HitTestResultBehavior.Continue; } } // Filter the hit test values for each object in the enumeration. public HitTestFilterBehavior MyHitTestFilter(DependencyObject o) { // Test for the object value you want to filter. if (o.GetType() == typeof(StopPoint)) { // Visual object's descendants are // NOT part of hit test results enumeration. return HitTestFilterBehavior.ContinueSkipChildren; } else { // Visual object is part of hit test results enumeration. return HitTestFilterBehavior.Continue; } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload