WPF treeview: как реализовать навигацию с помощью клавиатуры, как в Проводнике? - PullRequest
7 голосов
/ 23 сентября 2010

Я впервые использую древовидную структуру WPF и удивляюсь всем основным вещам, которые она делает , а не .Одним из них является клавиатурная навигация, реализованная в любом уважающем себя дереве, например в проводнике Windows или Regedit.

Вот как это должно работать:

Если представление дереваимеет фокус и я набираю (буквы / цифры), выделение должно переместиться к первому видимому (то есть расширенному) элементу под текущим выбранным элементом, который соответствует набранной мной строке, и отобразить ее.Если под текущим элементом найдено несоответствие, поиск должен продолжаться сверху.Если совпадение не найдено, выбранный элемент не должен изменяться.

Пока я продолжаю печатать, строка поиска увеличивается и поиск уточняется.Если я перестану набирать текст в течение определенного времени (2-5 секунд), строка поиска будет очищена.

Я готов программировать это «вручную» с нуля, но, поскольку это так просто, я подумал навернякакто-то уже сделал именно это.

Ответы [ 4 ]

3 голосов
/ 24 сентября 2010

Забавно, это не кажется популярной темой.Во всяком случае, в то же время я разработал решение проблемы, которая удовлетворяет меня:

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

2 голосов
/ 04 марта 2015

Я знаю, что это старая тема, но я думаю, что она по-прежнему актуальна для некоторых людей. Я сделал это решение. Он присоединен к KeyUp и событию TextInput в дереве WPF TreeView. Я использую TextInput в дополнение к KeyUp, так как мне было трудно переводить "национальные" символы в реальные символы с KeyEventArgs. Это прошло гораздо более гладко с TextInput.

// <TreeView Name="treeView1" KeyUp="treeView1_KeyUp" TextInput="treeView1_TextInput"/>

    private bool searchdeep = true;             // Searches in subitems
    private bool searchstartfound = false;      // true when current selected item is found. Ensures that you don't seach backwards and that you only search on the current level (if not searchdeep is true)
    private string searchterm = "";             // what to search for
    private DateTime LastSearch = DateTime.Now; // resets searchterm if last input is older than 1 second.

    private void treeView1_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
    {  
        // reset searchterm if any "special" key is pressed
        if (e.Key < Key.A)
            searchterm = "";

    }

    private void treeView1_TextInput(object sender, TextCompositionEventArgs e)
    {
        if ((DateTime.Now - LastSearch).Seconds > 1)
            searchterm = "";

        LastSearch = DateTime.Now;
        searchterm += e.Text;
        searchstartfound = treeView1.SelectedItem == null;

        foreach (var t in treeView1.Items)
            if (SearchTreeView((TreeViewItem) t, searchterm.ToLower()))
                break;
    }

   private bool SearchTreeView(TreeViewItem node, string searchterm)
    {
        if (node.IsSelected)
            searchstartfound = true;

        // Search current level first
        foreach (TreeViewItem subnode in node.Items)
        {
            // Search subnodes to the current node first
            if (subnode.IsSelected)
            {
                searchstartfound = true;
                if (subnode.IsExpanded)
                    foreach (TreeViewItem subsubnode in subnode.Items)
                        if (searchstartfound && subsubnode.Header.ToString().ToLower().StartsWith(searchterm))
                        {
                            subsubnode.IsSelected = true;
                            subsubnode.IsExpanded = true;
                            subsubnode.BringIntoView();
                            return true;
                        }
            }
            // Then search nodes on the same level
            if (searchstartfound && subnode.Header.ToString().ToLower().StartsWith(searchterm))
            {
                subnode.IsSelected = true;
                subnode.BringIntoView();
                return true;
            }
        }

        // If not found, search subnodes
        foreach (TreeViewItem subnode in node.Items)
        {
            if (!searchstartfound || searchdeep)
                if (SearchTreeView(subnode, searchterm))
                {
                    node.IsExpanded = true;
                    return true;
                }
        }

        return false;
    }
1 голос
/ 20 февраля 2011

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

Установка SelectedValuePath в ListView или TreeView дает такое поведение. Если элементы настроены по шаблону, то установка присоединенного свойства: TextSearch.TextPath в путь к свойству для поиска также поможет.

Надеюсь, это поможет, у меня определенно получилось.

0 голосов
/ 11 июля 2012

Это не очень просто, как мы ожидаем.Но лучшее решение, которое я нашел, здесь: http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode

Дайте мне знать, если вам нужно больше деталей.

...