首页 文章

在WPF中用鼠标检测儿童控件

提问于
浏览
1

我有一个WPF ParentUserControl 和一些 ChildUserControlA ChildUserControlB 等(也是WPF控件)

ChildUserControl 是包含一些其他基本元素(文本框,标签等)的控件

在主窗体的状态栏中,我需要显示当前鼠标覆盖的ChildUserControl的名称 .

所以,在ParentUserControl的MouseMove中,我获得了一个对象 myElement = Mouse.DirectlyOver ,因为我需要 ChildUserControl 's, but I obtain instead a ' 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 ......

2 回答

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

相关问题