2010-09-23 112 views
8

我第一次使用WPF treeview,並且驚訝於它所做的所有基本事情不是做的。其中之一是鍵盤導航,在任何自我尊重的樹視圖中實現,例如,在Windows資源管理器或註冊表中。WPF treeview:如何在資源管理器中實現鍵盤導航?

這是它應該是如何工作的:

如果樹視圖有焦點和I型(字母/數字)的選擇應該移動到第一個可見(又名展開)當前選擇的項目下面的項目是匹配我輸入的字符串並將其顯示在視圖中。如果在當前項目下找不到匹配項,則搜索應從頂部繼續。如果未找到匹配項,則所選項目不應更改。

只要我繼續輸入,搜索字符串就會增長,搜索就會被完善。如果我停止打字一段時間(2-5秒),搜索字符串將被清空。

我準備從頭開始編程這個「手工」,但由於這是如此非常基本,我以爲肯定有人已經完成了這個。

回答

4

有趣的是,這似乎並不是一個熱門話題。無論如何,在此期間,我已經開發出滿足我的問題的解決方案:

我將行爲附加到TreeViewItems。在那種行爲中,我處理KeyUp事件。在KeyUp事件處理程序中,我會從顯示的頂部到底部搜索可視化樹。如果我找到第一個匹配節點(其名稱以按下的鍵上的字母開頭),我選擇該節點。

+4

請問您附上一個代碼示例嗎?謝謝。 – 2012-02-07 11:51:59

+0

我也很感謝代碼示例 – 2012-07-30 03:25:22

+0

@Helge Klein:正如你所說,你已經開發出一個解決方案 - 你能分享代碼示例嗎? – digitguy 2012-12-12 02:00:16

1

我還在尋找鍵盤導航,令人驚訝的解決方案是模板化的項目。

在ListView或TreeView中設置SelectedValuePath會產生這種行爲。 如果項目是模板化的,然後將附加屬性:TextSearch.TextPath設置爲要搜索的屬性的路徑也可以實現。

希望這有助於,它絕對爲我工作。

+0

我無法得到這個工作。你能提供一個TreeView使用HierarchicalDataTemplate的情況下的代碼示例嗎? – 2011-02-20 20:32:23

0

這並不像我們預料的那樣簡單。但我找到的最佳解決方案是: http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode

讓我知道你是否需要更多的細節。

+0

當然,我知道那篇文章。它沒有描述如何實現鍵盤導航。 – 2012-07-11 07:52:15

+0

是的,我同意。雖然我們可以使用該文章中的方法實現簡單的搜索,但增量搜索非常困難。正如你所說,你已經開發了一個解決方案 - 你能分享代碼示例嗎? – digitguy 2012-07-12 09:44:58

1

我知道這是一個老話題,但我想這對某些人來說仍然是相關的。我做了這個解決方案。它附加到WPF TreeView上的KeyUp和TextInput事件。我除了使用KeyUp之外還使用TextInput,因爲我很難用「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; 
    } 
+0

謝謝!這很奇妙。我只需要將時間改爲500毫秒即可達到我需要的。 – JMooney 2018-01-17 16:13:32