【问题标题】:Detect Children Controls under mouse in WPF在WPF中检测鼠标下的儿童控件
【发布时间】:2012-04-17 15:50:56
【问题描述】:

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

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

在主窗体的状态栏中,我需要显示当前鼠标悬停的名称​​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...

【问题讨论】:

    标签: .net wpf vb.net wpf-controls


    【解决方案1】:

    您需要实现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 事件),只需这样做:

    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
    

    【讨论】:

    • 你可以在你的控件类的任何地方实现命中测试,但最好是让它可重用,创建一个继承 Panel 的类并将代码放在那里(在这种情况下你必须替换Me.ParentUserControl 与我)。
    • 一个UserControl不是一个CustomControl,它不能继承一个Panel... WPF中甚至不存在一个“panel”...
    • 你不必做一个新的UserControl库,只需要一个继承Panel..的“类”。不过话说回来,没必要
    • 你是什么意思的“面板”? System.Windows.Forms.Panel?
    • 我们谈论 WPF,而不是 WinForms、gliderkite )
    【解决方案2】:

    另一个答案可能是这样的 - 定义您关心的对象的确切类型并处理可视化树直到找到它们:

    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
    

    【讨论】:

      猜你喜欢
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多