How to identify which element was double clicked i

2019-01-26 22:26发布

问题:

I have a listbox. The listbox DataTemplate consists of few Text Blocks and some TextBoxes.

The issue is on mouse double click I need to find out on which element the double click was done, so as to do some further operations like make the TextBox editable and so on. At the same time I need to define some action for list double click also. So I can't handle mouse down separately for each component.

Hence, I need to handle the mouse down for the ListBox and find out on which element the double click was made.

I tried with below code, but it returns the ListBox's Name instead of TextBox's Name:

private void myListBox_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{    
    var mouseWasDownOn = e.Source as FrameworkElement;
    if (mouseWasDownOn != null)
    {
        string elementName = mouseWasDownOn.Name;
    }
}

I have also tried as per below questions

WPF Get Element(s) under mouse

How to know what control the mouse has clicked in a canvas?

Getting the Logical UIElement under the mouse in WPF

public void ListBox_MouseDownHandler(object sender, MouseButtonEventArgs e)
{
    HitTestResult target = VisualTreeHelper.HitTest(myListBoxName, e.GetPosition(myListBoxName));
    while(!(target is Control) && (target != null))
    {
        target = VisualTreeHelper.GetParent(target);
    }
}

But still could not find a solution. Hence please help me to get the element type or element name from double click.

回答1:

You can use FrameworkTemplate.FindName Method (String, FrameworkElement) for this purpose and it should works as you want:

private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is childItem)
            return (childItem)child;
        childItem childOfChild = FindVisualChild<childItem>(child);
        if (childOfChild != null)
            return childOfChild;
    }
    return null;
}

Then:

private void LstBox_OnPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    ListBoxItem ListBoxItem = (ListBoxItem)(lstBox.ItemContainerGenerator.ContainerFromIndex(lstBox.SelectedIndex));
    ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(ListBoxItem);
    DataTemplate myDataTemplate = contentPresenter.ContentTemplate;
    StackPanel temp = (StackPanel)myDataTemplate.FindName("myStackPanel", contentPresenter);
    //*so as to do some further operations like make the textbox editable and so on* as you want
   (temp.FindName("field1TextBox") as TextBox).IsReadOnly = false;
}

Based on your question that you said: The listbox's DataTemplate consists of few TextBlock and some TextBoxes. (I assumed they are inside a StackPanel)