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;