Получить правильный элемент древовидной структуры из события WPF PreviewMouseRightButtonDown элемента TreeView - PullRequest
0 голосов
/ 21 июля 2010

У меня есть WPF древовидная структура с динамическими уровнями (TreeView Item использует шаблон иерархических данных, который имеет привязываемый richtextbox) для моего приложения, мне нужно обработать событие PreviewMouseRightButtonDown TreeViewItem.

Когда я щелкаю правой кнопкой мыши на триоде в зависимости от уровня узла, это событие получает многократное попадание (равное уровню элемента дерева. Я думаю, что это связано с туннельным характером событий предварительного просмотра)

Может кто-нибудь помочь мне определить правильный удар, который дает точный вид дерева, на котором я щелкнул правой кнопкой мыши?

1 Ответ

1 голос
/ 21 июля 2010

Самый простой подход - использовать событие всплытия MouseRightButtonDown вместо события туннелирования PreviewMouseRightButtonDown . Вы можете пометить перенаправленное событие как обработанное, установив для свойства Handled объекта EventArgs значение true, что остановит вызов других обработчиков событий. Таким образом, только самый глубокий TreeViewItem получит событие.

Если вы не можете использовать событие Preview, другой подход заключается в использовании свойства OriginalSource из EventArgs, чтобы найти элемент пользовательского интерфейса, который был фактически нажат. Вероятно, это будет ваш RichTextBox, поэтому вам нужно будет использовать метод для поиска визуального предка типа TreeViewItem. Есть пример метода, чтобы получить предка данного типа в http://www.wpftutorial.net/LogicalAndVisualTree.html:

public static class VisualTreeHelperExtensions
{
    public static T FindAncestor<T>(DependencyObject dependencyObject)
        where T : class
    {
        DependencyObject target = dependencyObject;
        do
        {
            target = VisualTreeHelper.GetParent(target);
        }
        while (target != null && !(target is T));
        return target as T;
    }
}

Итак, вы можете вызвать ((DependencyObject)e.OriginalSource).FindAncestor<TreeViewItem>(), чтобы найти TreeViewItem, по которому щелкнули. Если вы делаете это таким образом, вы должны присоединить обработчик событий к самому TreeView, а не к TreeViewItems. Это поймает щелчок в любом TreeViewItem, так как все они находятся внутри дерева, но он будет вызываться только один раз.


Редактировать: Как вы заметили, этот метод не работает, если целью является FrameworkContentElement, потому что это не Visual. Вместо этого вы можете сделать что-то вроде этого:

public static class VisualTreeHelperExtensions
{
    public static T FindAncestor<T>(object dependencyObject)
        where T : DependencyObject
    {
        var target = (DependencyObject)dependencyObject;
        do
        {
            var visualParent = target is Visual ? VisualTreeHelper.GetParent(target) : null;
            if (visualParent != null)
            {
                target = visualParent;
            }
            else
            {
                var logicalParent = LogicalTreeHelper.GetParent(target);
                if (logicalParent != null)
                {
                    target = logicalParent;
                }
                else
                {
                    return null;
                }
            }
        }
        while (!(target is T));
        return (T)target;
    }
}

Тогда вы сможете получить TreeViewItem из OriginalSource, выполнив VisualTreeHelperExtensions.FindAncestor<TreeViewItem>(e.OriginalSource).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...