WPF用户控制测试

WPF用户控制测试,wpf,user-controls,hittest,Wpf,User Controls,Hittest,我有以下用户控件:一个点及其名称: <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/mark

我有以下用户控件:一个点及其名称:

<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">

   <StackPanel>
      <Ellipse Stroke="DarkBlue" Fill="LightBlue" Height="10" Width="10"/>
      <TextBlock Text="Eiffel Tower"/>        
  </StackPanel>
</UserControl>

这很酷

现在,我有一个面板,在这个面板中,我需要恢复我用鼠标点击的停止点:

public partial class StopsPanel : UserControl
{
    private List<StopPoint> hitList = new List<StopPoint>();
    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 > 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;
        }
    }
}
public部分类StopsPanel:UserControl
{
私有列表hitList=新列表();
专用EllipseGeometry hitArea=新的EllipseGeometry();
公共停车带()
{
初始化组件();
初始化();
}
私有void初始化()
{
foreach(StopsCanvas.Children中的停止点)
{
point.Background=brusks.LightBlue;
}
}
MouseLeftButtonDown上的私有void(对象发送器,MouseButtonEventArgs e)
{
//初始化:
初始化();
//获取鼠标单击点:
点pt=e.GetPosition(StopsCanvas);
//定义命中测试区域:
hitArea=新椭圆梯度法(pt,1.0,1.0);
hitList.Clear();
//呼叫测试方法:
VisualTreeHelper.HitTest(StopsCanvas,null,
新HitTestResultCallback(HitTestCallback),
新的几何参数(HIT区域);
如果(hitList.Count>0)
{
foreach(命中列表中的停止点)
{
//更改矩形填充颜色(如果命中):
point.Background=brusks.LightCoral;
}
MessageBox.Show(string.Format(
“您命中了{0}个停止点(s)”,命中列表.Count));
}
}
公共HitTestResultBehavior HitTestCallback(HitTestResult结果)
{
如果(result.VisualHit是StopPoint)
{
//
//--------千万不要进入这里!!!:(
//
//检索命中测试的结果。
相交细节相交细节=
((GeometryHitterResult)结果)。交叉详细信息;
开关(交叉详图)
{
案例交叉详细信息。完整内容:
//将命中测试结果添加到列表中:
hitList.Add((停止点)result.VisualHit);
返回HitTestResultBehavior。是否继续;
案例交集详细信息。交集:
//将行为设置为在所有z顺序级别返回视觉效果:
返回HitTestResultBehavior。是否继续;
case IntersectionDetail.FullyInside:
//将行为设置为在所有z顺序级别返回视觉效果:
返回HitTestResultBehavior。是否继续;
违约:
返回HitTestResultBehavior.Stop;
}
}
其他的
{
返回HitTestResultBehavior。是否继续;
}
}
}
因此,正如您所看到的,HitTest从不按原样识别用户控件(StopPoint),而是识别其组件(TextBlock、Ellipse甚至Border)。
当我将业务对象与StopPoint元素关联时,我需要在鼠标放置时获取它,而不是它的组成元素

有办法吗

编辑:

使用过滤器(现在,它根本不在HitTestCallback中输入):

使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
使用System.Windows.Media;
命名空间ShapeTester
{
/// 
///StopsPanel.xaml的交互逻辑
/// 
公共部分类StopsPanel:UserControl
{
私有列表hitList=新列表();
专用EllipseGeometry hitArea=新的EllipseGeometry();
公共停车带()
{
初始化组件();
初始化();
}
私有void初始化()
{
foreach(StopsCanvas.Children中的停止点)
{
point.Background=brusks.LightBlue;
}
}
MouseLeftButtonDown上的私有void(对象发送器,MouseButtonEventArgs e)
{
//初始化:
初始化();
//获取鼠标单击点:
点pt=e.GetPosition(StopsCanvas);
//定义命中测试区域:
hitArea=新椭圆梯度法(pt,1.0,1.0);
hitList.Clear();
//呼叫测试方法:
VisualTreeHelper.HitTest(StopsCanvas,
新HitTestFilterCallback(MyHitTestFilter),
新HitTestResultCallback(HitTestCallback),
新的几何参数(HIT区域);
如果(hitList.Count>0)
{
foreach(命中列表中的停止点)
{
//更改矩形填充颜色(如果命中):
point.Background=brusks.LightCoral;
}
MessageBox.Show(string.Format(
“您命中了{0}个停止点(s)”,命中列表.Count));
}
}
公共HitTestResultBehavior HitTestCallback(HitTestResult结果)
{
如果(result.VisualHit是StopPoint)
{
//
//--------千万不要进入这里!!!:(
//
//检索命中测试的结果。
相交细节相交细节=
((GeometryHitterResult)结果)。交叉详细信息;
开关(交叉详图)
{
案例交叉详细信息。完整内容:
//将命中测试结果添加到列表中:
hitList.Add((停止点)result.VisualHit);
返回HitTestResultBehavior。是否继续;
案例交集详细信息。交集:
//将行为设置为在所有z顺序级别返回视觉效果:
返回HitTestResultBehavior。是否继续;
case IntersectionDetail.FullyInside:
//设置返回视觉效果的行为
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace ShapeTester
{
    /// <summary>
    /// Interaction logic for StopsPanel.xaml
    /// </summary>
    public partial class StopsPanel : UserControl
    {
        private List<StopPoint> hitList = new List<StopPoint>();
        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 > 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;
            }
        }
    }
}
var element = result.VisualHit;
while(element != null && !(element is StopPoint))
    element = VisualTreeHelper.GetParent(element);

if(element == null) return;