2009-07-22 12 views
10

Standardowy dokument WPF tree view nie obsługuje wielu wyborów.Drzewo widoku drzewa WPF z wieloma zaznaczeniami

Jak dodać widok drzewa, który obsługuje wiele zaznaczeń do mojej aplikacji WPF? Produkty handlowe są w porządku (jestem obecnie świadomy jednej realizacji handlowych - http://www.telerik.com/products/wpf/treeview.aspx)

+0

Spójrz na tej dyskusji: http://stackoverflow.com/questions/459375/customizing-the-treeview-to-allow-multi-select/9297158#9297158 –

+0

Sprawdź moją odpowiedź tutaj: http://stackoverflow.com/a/13412801/166452 –

Odpowiedz

1

w zależności od dokładnego semantyki jest pragnienie, rozwiązanie może być bardzo prosta:

Jeśli korzeń drzewa wcale nie jest TreeView - na przykład, jeśli jest to zwykły ItemsControl - wszystkie TreeViewItems w drzewie zostaną niezależnie zaznaczone, więc w zasadzie otrzymasz mulitiselect za darmo. Po prostu użyj ItemsControl zamiast TreeView dla katalogu głównego drzewa.

Rozwiązanie to ma tę zaletę, że jest wyjątkowo łatwe do wdrożenia. Różni się on od rozwiązania mattdlonga tym, że:

  • Jego rozwiązanie odznacza wszystkie inne elementy po kliknięciu elementu, więc trzeba klikać elementy z naciśniętym klawiszem Ctrl do wielokrotnego wyboru.
  • Za pomocą tego rozwiązania jedno kliknięcie wybierze/odznaczy wybraną pozycję, ale nie ma możliwości szybkiego wybrania elementu i jednoczesnego anulowania zaznaczenia wszystkich pozostałych.

Kolejną różnicą jest to, że nawigacja po klawiaturze (klawisze strzałek) w jego rozwiązaniu odznacza wszystkie elementy, podczas gdy w tym rozwiązaniu nawigacja po klawiaturze nie odznacza pozycji.

Powinieneś wybrać te rozwiązania w oparciu o preferowaną semantykę (jedno kliknięcie, aby dodać element do ctrl-kliknięcia, aby dodać element, itp.). Jeśli chcesz bardziej zaawansowanej semantyki, takiej jak Shift-Click, itp., Jest względnie do dodania.

Należy pamiętać, że można również niestandardowe TreeViewItems styl używając ToggleButton lub CheckBox gdziekolwiek w ItemContainerTemplate który ma Checked={Binding IsSelected}. To pozwala użytkownikowi wybrać elementy, klikając na ToggleButton lub CheckBox.

+1

Mam pewne doświadczenie z drzewami w interfejsie użytkownika, aby nauczyć się jednej zasady - jest tak wiele szczegółów we wprowadzaniu wielu selekcji poprawnie, że naprawdę nie chcę weź tę drogę. Wolę kogoś, kto zajmuje się projektowaniem formantów interfejsu użytkownika i kto już zainwestował w testowanie i dostrajanie, zamiast produkować coś szybko, co będzie ciągnąć zasoby do naprawy i utrzymania. To jest miłe jako ćwiczenie programistyczne, przyznane. – mark

+0

Myślę, że źle zrozumiałeś moją odpowiedź. Próbowałem powiedzieć, że TreeViewItem obsługuje prosty multiselection po wyjęciu z pudełka, więc ** nie musisz nic pisać. ** Jeśli podoba Ci się wbudowana multiselectionowa semantyka, możesz po prostu z niego skorzystać. Jeśli chcesz czegoś innego niż wbudowane zachowanie multiselect, ** wtedy ** będziesz musiał albo kupić kontrolkę albo napisać kod jak opisuje Mattdlong. –

+2

Kiedy próbuję zastąpić formant TreeView narzędziem ItemsControl, nie powiedzie się to ze śledzeniem stosu dłuższym niż strona. Styl dla TreeViewItem nie może być zastosowany do tego elementu sterującego lub coś podobnego. Jak to ma działać? Czy jest to nadal hierarchiczna kontrola drzewa, czy też stanie się wtedy płaską listą? (W takim przypadku byłoby to bezużyteczne.) – ygoe

12

Poniższy kod działa poprawnie i jest znacznie prostszy. Jednak zwrotem jest użycie własności niepublicznej IsSelectionChangeActive z klasy widoku drzewa. Kod poniżej:

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

Nice! Metoda, która działa, używa istniejącego TreeView (tzn. Nie przepisuje go od nowa) i wykorzystuje własną zależność TreeView od IsSelected. Musiał zmienić TreeViewItem na element, który ustawiłem wiązania, ale to było o tym. Dzięki. – markmuetz

+0

Ma kilka problemów. Jednym z nich jest to, że nie można CTRL + wybierz i Ctrl + odznacz ten sam element. Zakładam, że dzieje się tak, ponieważ żadne zdarzenie SelectedItemChanged nie jest wyzwalane po dwukrotnym kliknięciu tego samego elementu. Zajmuję się tym. I otwarte pytanie, w jaki sposób można użyć powiązania danych do SelectedItem z wielokrotnym wyborem. – ygoe

+0

Czy zdołałeś kiedyś naprawić błąd Ctrl + select i Ctrl + deselect? – user589195

Powiązane problemy