0

This is a WPF application.

I'm trying to get the control directly under the mouse and it's proving to be a surprising pain.

Mouse.DirectlyOver, InputHitTest and VisualTreeHelper.HitTest all reference the VISUAL tree. I'm trying to grab the control itself.

Example: If I have a TextBox and use any of the above, it will return a TextBoxView whereas I want the TextBox itself.

This is happening inside of a PreviewLeftButtonDown event. Sender is not an option as Sender is always a ListViewItem for me. If I check e.OriginalSource it is still the VisualTree element and not the actual control.

Happy to explain further if need be.

Thanks

tronious
  • 1,547
  • 2
  • 28
  • 45

3 Answers3

4

You just need to walk up the visual tree until you find the type you want. Here's a link to some code.

Here's the code from that link

// walk up the visual tree to find object of type T, starting from initial object
public static T FindUpVisualTree<T>(DependencyObject initial) where T : DependencyObject
{
    DependencyObject current = initial;

    while (current != null && current.GetType() != typeof(T))
    {
         current = VisualTreeHelper.GetParent(current);
    }
    return current as T;   
}
mdm20
  • 4,475
  • 2
  • 22
  • 24
  • Thanks for your reply. This would work but I don't like walking the tree as this is going to happen often. Also I'd be concerned about inadvertently hitting the wrong TextBox (what if a control is templated and there are mutliple textboxes leading up to the parent.(=) In the end JustinPihony's answer fulfills my need. – tronious Mar 07 '13 at 16:53
1

Walk up the visual tree until you find a UIElement:

public UIElement FindUIElement(DependencyObject visualTreeNode)
{
    UIElement elem;
    while ((elem = (visualTreeNode as UIElement)) != null)
        visualTreeNode = VisualTreeHelper.GetParent(visualTreeNode);
    return elem;
}
Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
1

I agree with mdm20 that the only way to get to the Textbox is by traversing up to the parent. In fact, here is a link to the same question asked a couple of years ago, with the same answer. If you want to limit unnecessary tree traversal, then you could stop searching once you hit the ListViewItem, as anything above that point is not what you are looking for anyway.

However, add the last link and this one together, and it actually seems to me that you already have your answer. If a TextBoxView is returned, then you know that a textbox was hit. You could even cache the incoming TextBox that goes through the HitTestFilterCallBack potentially, but that is more of a theory and possibly bug prone. However, going down that path, you could just test if the TextBox coming through the filter is the parent of the TextBoxView

Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
  • This will be accepted answer. TextBoxView is what I ended up using. The TextBoxView is what actually contains the text anyways which is what I was really after. I wanted to AVOID triggering a drag if the user was dragging within a textBox to select some text. Thanks – tronious Mar 07 '13 at 16:55