2010-02-11 16 views
20

Po rozwinięciu elementów w moim widoku drzewa, aby przewijanie było konieczne, pojawi się pasek przewijania. Nie jest jednak przewijany w dół dla nowo rozwiniętej gałęzi elementów - przycina się je u dołu kontrolki. Ponieważ nadal rozwijam elementy na dole drzewa, muszę ręcznie przewijać w dół, aby zobaczyć nowe dzieci. Ktoś ma sugestię, jak automatycznie przewinąć, aby pokazać nowo rozwinięte elementy?Przeglądarka drzewa WPF - jak przewinąć tak rozwiniętą gałąź jest widoczna

Odpowiedz

16

W TreeView, obsłużyć zdarzenie TreeViewItem.Expanded (można to zrobić na poziomie TreeView z powodu bulgotania zdarzeń). W rozwiniętym module obsługi wywołaj BringIntoView na TreeViewItem, który podniósł wydarzenie.

Może zaistnieć potrzeba odrobiny prób i błędów, aby zdobyć TreeViewItem w kodzie obsługi zdarzenia. Myślę (nie sprawdziłem), że argumentem nadawcy do rozwiniętej obsługi zdarzeń będzie TreeView (ponieważ tam jest dołączona obsługa zdarzeń), a nie TreeViewItem. A e.Source lub e.OriginalSource może być elementem w szablonie danych TreeViewItem. Być może będziesz musiał użyć VisualTreeHelper, aby podejść do drzewa wizualnego, aby znaleźć TreeViewItem. Ale jeśli użyjesz debuggera do sprawdzenia nadawcy i RoutedEventArgs, to powinno to być proste.

(Jeśli potrafisz sprawić, żeby to działało i chcesz go spakować, więc nie musisz dołączać tego samego programu obsługi zdarzeń do każdego TreeView, powinno być łatwo zamknąć go jako attached behaviour, co pozwoli ci ., aby zastosować go deklaratywnie, w tym poprzez style)

+0

To naprawdę działa idealnie, myślałem, że będzie problem, ponieważ chcę skupić się na rozszerzonych elementach potomnych, a nie na przedmiocie, który się rozwinął, ale działa dokładnie tak, jak tego chciałem. Bardzo dziękuję za sugestie dołączonych zachowań, jeszcze lepiej. – Jared

+0

Właściwie to działa dla mojego treeview, gdzie całkowicie przesłonię szablon treeviewitem, ale nie działa dla mojego prostszego widoku drzewa, gdzie używam domyślnego szablonu treeviewitem ... nie wiem dlaczego – Jared

2

Dzięki itowlson za odpowiedź, oto rozszerzony kod zdarzenia handler, który pracuje dla obu moich drzew

private static void Tree_Expanded(object sender, RoutedEventArgs e) 
{ 
    // ignore checking, assume original source is treeviewitem 
    var treeViewItem = (TreeViewItem)e.OriginalSource; 

    var count = VisualTreeHelper.GetChildrenCount(treeViewItem); 

    for (int i = count - 1; i >= 0; --i) 
    { 
     var childItem = VisualTreeHelper.GetChild(treeViewItem, i); 
     ((FrameworkElement)childItem).BringIntoView(); 
    } 

    // do NOT call BringIntoView on the actual treeviewitem - this negates everything 
    //treeViewItem.BringIntoView(); 
} 
+0

Co to jest część XAML do tego proszę? Próbowałem dostosować niektóre inne fragmenty XAML z tej strony, ale nie działałoby to z powodu błędu, którego nie rozumiem. – ygoe

+0

Nieważne, rozgryzłem to. Musisz usunąć "statyczny" z powyższego podpisu metody, następnie następujące działania XAML: ygoe

12

użyć właściwość zależność na spuście isSelected:

<Style TargetType="{x:Type TreeViewItem}"> 
<Style.Triggers> 
    <Trigger Property="IsSelected" Value="True"> 
    <Setter Property="commands:TreeViewItemBehavior.BringIntoViewWhenSelected" Value="True" /> 
    </Trigger> 
</Style.Triggers> 

Oto kod dla właściwości zależności:

public static bool GetBringIntoViewWhenSelected(TreeViewItem treeViewItem) 
{ 
    return (bool)treeViewItem.GetValue(BringIntoViewWhenSelectedProperty); 
} 

public static void SetBringIntoViewWhenSelected(TreeViewItem treeViewItem, bool value) 
{ 
    treeViewItem.SetValue(BringIntoViewWhenSelectedProperty, value); 
} 

public static readonly DependencyProperty BringIntoViewWhenSelectedProperty = 
    DependencyProperty.RegisterAttached("BringIntoViewWhenSelected", typeof(bool), 
    typeof(TreeViewItemBehavior), new UIPropertyMetadata(false, OnBringIntoViewWhenSelectedChanged)); 

static void OnBringIntoViewWhenSelectedChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e) 
{ 
    TreeViewItem item = depObj as TreeViewItem; 
    if (item == null) 
    return; 

    if (e.NewValue is bool == false) 
    return; 

    if ((bool)e.NewValue) 
    item.BringIntoView(); 
} 
+1

To rozwiązanie działa nawet po ustawieniu zaznaczenia z kodu. Pozostałe warianty działają tylko wtedy, gdy ręcznie naciśniesz węzeł z drzewa. – alexandrudicu

+0

To jest świetne, działa jak czar! –

+1

Powinno istnieć przynajmniej odniesienie do oryginalnego źródła: [Wprowadzenie do Attached Behaviors w WPF] (https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF) – bokibeg

13

Można użyć prostego EventSetter w stylu TreeViewItem do wywołania programu obsługi zdarzeń, gdy wybrana jest pozycja. Następnie wywołaj BringIntoView dla przedmiotu.

<TreeView > 
<TreeView.ItemContainerStyle> 
    <Style TargetType="{x:Type TreeViewItem}"> 
    <EventSetter Event="Selected" Handler="TreeViewSelectedItemChanged" /> 
    </Style> 
</TreeView.ItemContainerStyle> 

</TreeView> 

private void TreeViewSelectedItemChanged(object sender, RoutedEventArgs e) 
{ 
    TreeViewItem item = sender as TreeViewItem; 
    if (item != null) 
    { 
     item.BringIntoView(); 
     e.Handled = true; 
    } 
} 
+0

Rewizja została dokonana przez przypadek; Przepraszam.Tak dzieje się, gdy kot przechodzi przez klawiaturę. Potrzebują filtra kota na SO. :-) –

Powiązane problemy