我有一个WPF ParentUserControl
和一些ChildUserControlA
ChildUserControlB
等(也是WPF控件)
ChildUserControl
是包含一些其他基本元素(文本框,标签等)的控件
在主窗体的状态栏中,我需要显示当前鼠标的名称 ChildUserControl 。
所以,在 ParentUserControl 的MouseMove中,我获得了一个对象myElement = Mouse.DirectlyOver
,因为我需要 ChildUserControl 的最顶层,但我获得的是'System.Windows.Controls.TextBlock'(ChildUserControl的一部分)......
如何解决这个问题?
当我在MyChildControl上鼠标时,我需要检测到MyChildControl,而不是它的子元素。
按照这个顺序,我在MyChildControl上使用了以下内容:
Protected Overrides Function HitTestCore(
hitTestParameters As PointHitTestParameters) As HitTestResult
Return New PointHitTestResult(Me, hitTestParameters.HitPoint)
End Function
但无论如何我有时会得到文本块,有时是ChildUserControl ......
答案 0 :(得分:3)
您需要实施Hit-Testing。因此,如果您想获取区域内的所有元素,可以使用HitTestResultCallback。一个例子:
Dim Elements As New List(Of FrameworkElement)
Public Function GetVisuals(ByVal Region As Geometry) As List(Of FrameworkElement)
If Region Is Nothing Then Return Nothing
Dim Parameters As New GeometryHitTestParameters(Region)
Elements.Clear()
Dim Callback As New HitTestResultCallback(AddressOf Me.HitTestCallBack)
VisualTreeHelper.HitTest(Me.ParentUserControl, Nothing, Callback, Parameters)
Return Me.Elements
End Function
Private Function HitTestCallBack(ByVal Result As HitTestResult) As HitTestResultBehavior
If Result IsNot Nothing Then
Dim GeometryRes As GeometryHitTestResult = CType(Result, GeometryHitTestResult)
Dim Element As FrameworkElement = TryCast(Result.VisualHit, FrameworkElement)
If Element IsNot Nothing AndAlso GeometryRes.IntersectionDetail = IntersectionDetail.FullyContains Then
Me.Elements.Add(Element)
End If
End If
Return HitTestResultBehavior.Continue
End Function
这样,Elements列表包含GeometryHitTestResult.IntersectionDetail指定的所有元素,如果你想(例如)知道鼠标位置下的元素(MouseDown Event),只需这样做:
Dim Region As New RectangleGeometry(New Rect(e.GetPosition(Me.MyGrid), New Size(1, 1)))
Dim Elements As List(Of FrameworkElement) = Me.GetVisuals(Region)
这就是我在评论中的意思:
Public Class DrawingCanvas
Inherits Panel
Public Function GetVisuals(ByVal Region As Geometry) As List(Of DrawingVisual)
End Function
Private Function HitTestCallBack(ByVal Result As HitTestResult) As HitTestResultBehavior
End Function
End Class
答案 1 :(得分:1)
另一个答案可能是这样的 - 定义你关心的对象的确切类型,然后处理可视树,直到找到它们为止:
Private myTypes As New List(Of Type)()
Public Sub New()
InitializeComponent()
myTypes.Add(GetType(ComboBox))
myTypes.Add(GetType(CheckBox))
myTypes.Add(GetType(RadioButton))
myTypes.Add(GetType(TabControl))
myTypes.Add(GetType(Button))
myTypes.Add(GetType(Label))
myTypes.Add(GetType(GroupBox))
myTypes.Add(GetType(Window))
End Sub
Private Sub Window_MouseMove(sender As Object, e As MouseEventArgs)
Dim x As DependencyObject = _
DirectCast(e.MouseDevice.DirectlyOver, DependencyObject)
Dim t As Type = x.GetType
While Not myTypes.Contains(t)
x = VisualTreeHelper.GetParent(x)
If x Is Nothing Then Exit While
t = x.GetType
End While
If x IsNot Nothing Then
Console.WriteLine(x.ToString())
Else
Console.WriteLine("Nothing")
End If
End Sub