2009-07-22 32 views
10

Tiêu chuẩn WPF tree view không hỗ trợ nhiều lựa chọn.WPF TreeView với nhiều lựa chọn

Làm cách nào để thêm chế độ xem dạng cây hỗ trợ nhiều lựa chọn cho ứng dụng WPF của tôi? sản phẩm thương mại cũng tốt (Tôi hiện đã biết về một thực hiện thương mại - http://www.telerik.com/products/wpf/treeview.aspx)

+0

Hãy nhìn vào cuộc thảo luận này: http://stackoverflow.com/questions/459375/customizing-the-treeview-to-allow-multi-select/9297158#9297158 –

+0

Kiểm tra câu trả lời của tôi ở đây: http://stackoverflow.com/a/13412801/166452 –

Trả lời

1

Tùy thuộc vào ngữ nghĩa chính xác mà bạn mong muốn, các giải pháp có thể rất đơn giản:

Nếu thư mục gốc của cây của bạn là bất cứ điều gì nhưng một TreeView - ví dụ nếu nó là một đồng bằng ItemsControl - tất cả TreeViewItems trong cây sẽ được lựa chọn độc lập để bạn về cơ bản nhận được mulitiselect miễn phí. Vì vậy, chỉ cần sử dụng một số ItemsControl thay vì một số TreeView cho thư mục gốc của cây của bạn.

Giải pháp này có lợi ích vô cùng đơn giản để thực hiện. Nó khác với giải pháp của mattdlong trong đó:

  • Giải pháp của ông bỏ chọn tất cả các mục khác khi một mục được nhấp, vì vậy bạn phải bấm ctrl để chọn nhiều mục.
  • Với giải pháp này, một nhấp chuột duy nhất sẽ chọn/bỏ chọn mục bạn đã nhấp vào, nhưng không có cách nào để nhanh chóng chọn một mục và đồng thời bỏ chọn tất cả các mục khác.

Sự khác biệt là điều hướng bàn phím (phím mũi tên) trong giải pháp của anh ấy bỏ chọn tất cả các mục, trong khi điều hướng bàn phím giải pháp này không bỏ chọn mục.

Bạn nên chọn giữa các giải pháp này dựa trên ngữ nghĩa bạn thích (nhấp chuột duy nhất để thêm mục vs nhấn ctrl để thêm mục, v.v.). Nếu bạn muốn có thêm ngữ nghĩa nâng cao, chẳng hạn như Shift-Click, vv, nó tương đối để thêm vào.

Lưu ý rằng bạn cũng có thể TreeViewItems custom style sử dụng một ToggleButton hoặc CheckBox bất cứ nơi nào trong ItemContainerTemplateChecked={Binding IsSelected}. Điều này cho phép người dùng chọn các mục bằng cách nhấp vào ToggleButton hoặc CheckBox.

+1

Tôi có một số kinh nghiệm về cây trong giao diện người dùng để tìm hiểu một quy tắc - có quá nhiều chi tiết trong việc triển khai nhiều lựa chọn chính xác, mà tôi thực sự không muốn đi theo con đường này. Tôi thích một ai đó, doanh nghiệp của họ đang thiết kế các điều khiển giao diện người dùng và đã đầu tư vào kiểm tra và điều chỉnh, thay vì sản xuất một cái gì đó nhanh chóng, sẽ liên tục thu hút các nguồn lực để sửa chữa và bảo trì. Nó là tốt đẹp như một bài tập lập trình, được cấp. – mark

+0

Tôi nghĩ rằng bạn hiểu lầm câu trả lời của tôi. Những gì tôi đã cố gắng để nói là TreeViewItem hỗ trợ multiselection đơn giản ra khỏi hộp, vì vậy ** bạn không cần phải viết bất cứ điều gì cả. ** Nếu bạn thích ngữ nghĩa đa ngữ được xây dựng trong nó, bạn chỉ có thể sử dụng nó. Nếu bạn muốn một cái gì đó khác với hành vi đa lựa chọn tích hợp, ** sau đó ** bạn sẽ phải mua một điều khiển hoặc viết mã như mô tả mattdlong. –

+2

Khi tôi cố gắng thay thế một điều khiển TreeView bằng một ItemsControl, tất cả đều không thành công với một dấu vết ngăn xếp dài hơn một trang. Một kiểu cho TreeViewItem không thể được áp dụng cho điều khiển đó, hoặc một cái gì đó. Vì vậy, làm thế nào là nghĩa vụ phải làm việc? Nó vẫn là một cây điều khiển phân cấp hay nó sẽ trở thành một danh sách phẳng? (Trong trường hợp đó nó sẽ là vô dụng.) – ygoe

12

Mã bên dưới hoạt động tốt và đơn giản hơn rất nhiều. Tuy nhiên, việc vẽ lại là việc sử dụng thuộc tính không công khai, IsSelectionChangeActive, của lớp treeview. Mã bên dưới:

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); 
    } 
    }; 

} 
+1

Rất tuyệt! Một phương thức hoạt động, sử dụng TreeView hiện tại (tức là không viết lại từ đầu) và sử dụng tùy chọn IsSelected dependency propterty của TreeView. Đã phải thay đổi TreeViewItem thành mục mà tôi đã đặt ràng buộc, nhưng đó là về nó. Cảm ơn. – markmuetz

+0

Nó có một vài vấn đề. Một trong số đó là bạn không thể Ctrl + select và Ctrl + bỏ chọn cùng một mục. Tôi cho rằng đó là vì không có sự kiện SelectedItemChanged được kích hoạt khi nhấp vào cùng một mục hai lần. Tôi đang nhìn vào nó. Và một câu hỏi mở là làm thế nào tôi có thể sử dụng dữ liệu ràng buộc với SelectedItem với nhiều lựa chọn. – ygoe

+0

Bạn đã từng sửa lỗi Ctrl + select và Ctrl + bỏ chọn lỗi chưa? – user589195

Các vấn đề liên quan