2009-07-22 62 views
10

標準的WPF tree view不支持多選。帶多選的WPF TreeView

如何添加支持多選的樹視圖到我的WPF應用程序?商業產品都很好(我目前知道的一個商業實現的 - http://www.telerik.com/products/wpf/treeview.aspx

+0

看看這個討論: http://stackoverflow.com/questions/459375/customizing-the-treeview-to-allow-multi-select/9297158#9297158 – 2012-02-15 16:29:52

+0

檢查我的答案在這裏:http://stackoverflow.com/a/13412801/166452 – 2012-11-16 08:21:32

回答

1

取決於你想要的精確語義,解決方案可能是非常簡單的:

如果你的樹的根是什麼,但一個TreeView - 例如,如果它是一個普通的ItemsControl - 樹中的所有TreeViewItems將獨立選擇,所以你基本上可以免費獲得mulitiselect。因此,只需使用ItemsControl而不是TreeView作爲樹的根。

該解決方案具有實現起來非常簡單的優點。它不同於mattdlong的解決方案在於:

  • 他的解決辦法取消選擇所有其他項目被點擊的項目時,所以你必須按住Ctrl鍵單擊項目多選。
  • 使用此解決方案,只需點擊一下即可選擇/取消選擇您點擊的項目,但無法快速選擇項目並同時取消選擇所有其他項目。

另一個區別是他的解決方案中的鍵盤導航(箭頭鍵)取消選擇所有項目,而在此解決方案中,鍵盤導航不取消選擇項目。

你應該根據你喜歡的語義在這些解決方案之間進行選擇(單擊來添加項目,按住Ctrl的同時點擊添加項目等)。如果你想要更高級的語義,比如Shift-Click等,那就相對要加。你也可以在具有Checked={Binding IsSelected}ItemContainerTemplate使用ToggleButtonCheckBox自定義樣式TreeViewItems隨時隨地

注意。這允許用戶通過點擊ToggleButtonCheckBox來選擇項目。

+1

我有一些用戶界面樹學習一個規則的經驗 - 有很多細節正確地實施多項選擇,我真的不希望走這條路。我更喜歡某個人,他的業務是設計UI控件,並且已經投入了測試和調整,而不是快速生成某些東西,這會不斷吸取資源進行修復和維護。作爲編程練習,這是很好的。 – mark 2010-01-19 07:36:30

12

下面的代碼工作正常,更簡單。然而,退格是使用treeview類的非公共屬性IsSelectionChangeActive。下面的代碼:

private static readonly PropertyInfo IsSelectionChangeActiveProperty 
    = typeof (TreeView).GetProperty 
    (
     "IsSelectionChangeActive", 
     BindingFlags.NonPublic | BindingFlags.Instance 
    ); 

public static void AllowMultiSelection(TreeView treeView) 
{ 
    if (IsSelectionChangeActiveProperty==null) return; 

    var selectedItems = new List<TreeViewItem>(); 
    treeView.SelectedItemChanged += (a, b) => 
    { 
    var treeViewItem = treeView.SelectedItem as TreeViewItem; 
    if (treeViewItem == null) return; 

    // allow multiple selection 
    // when control key is pressed 
    if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) 
    { 
     // suppress selection change notification 
     // select all selected items 
     // then restore selection change notifications 
     var isSelectionChangeActive = 
     IsSelectionChangeActiveProperty.GetValue(treeView, null); 

     IsSelectionChangeActiveProperty.SetValue(treeView, true, null); 
     selectedItems.ForEach(item => item.IsSelected = true); 

     IsSelectionChangeActiveProperty.SetValue 
     (
     treeView, 
     isSelectionChangeActive, 
     null 
    ); 
    } 
    else 
    { 
     // deselect all selected items except the current one 
     selectedItems.ForEach(item => item.IsSelected = (item == treeViewItem)); 
     selectedItems.Clear(); 
    } 

    if (!selectedItems.Contains(treeViewItem)) 
    { 
     selectedItems.Add(treeViewItem); 
    } 
    else 
    { 
     // deselect if already selected 
     treeViewItem.IsSelected = false; 
     selectedItems.Remove(treeViewItem); 
    } 
    }; 

}