2009-12-17 18 views
5

Ich habe einen Scrollviewer, der eine Baumansicht umschließt.Scrollen zum ausgewählten Treeviewitem in einem Scrollview

Ich bevölkere die Baumansicht programmatisch (es ist nicht gebunden), und erweitern Sie die Baumansicht zu einem vorgegebenen TreeViewitem. Das alles funktioniert gut.

Mein Problem ist, dass, wenn der Baum erweitert wird, ich möchte die Scrollview, die Eltern der Treeview zu dem Treeviewitem, das ich gerade erweitert. Irgendwelche Ideen? - Denken Sie daran, dass die Baumansicht nicht jedes Mal die gleiche Struktur hat, wenn sie erweitert wird, so dass nur die aktuelle Bildlaufposition gespeichert und wieder zurückgesetzt wird ...

Antwort

4

Ich hatte das gleiche Problem, mit der TreeView scrollt nicht zum ausgewählten Element.

Nach dem Erweitern der Struktur zum ausgewählten TreeViewItem, habe ich eine Dispatcher Helper-Methode aufgerufen, um die UI zu aktualisieren, und dann den TransformToAncestor für das ausgewählte Element verwendet, um seine Position im ScrollViewer zu finden. Hier ist der Code:

// Allow UI Rendering to Refresh 
    DispatcherHelper.WaitForPriority(); 

    // Scroll to selected Item 
    TreeViewItem tvi = myTreeView.SelectedItem as TreeViewItem; 
    Point offset = tvi.TransformToAncestor(myScroll).Transform(new Point(0, 0)); 
    myScroll.ScrollToVerticalOffset(offset.Y); 

Hier wird der DispatcherHelper Code:

public class DispatcherHelper 
{ 
    private static readonly DispatcherOperationCallback exitFrameCallback = ExitFrame; 

    /// <summary> 
    /// Processes all UI messages currently in the message queue. 
    /// </summary> 
    public static void WaitForPriority() 
    { 
     // Create new nested message pump. 
     DispatcherFrame nestedFrame = new DispatcherFrame(); 

     // Dispatch a callback to the current message queue, when getting called, 
     // this callback will end the nested message loop. 
     // The priority of this callback should be lower than that of event message you want to process. 
     DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
      DispatcherPriority.ApplicationIdle, exitFrameCallback, nestedFrame); 

     // pump the nested message loop, the nested message loop will immediately 
     // process the messages left inside the message queue. 
     Dispatcher.PushFrame(nestedFrame); 

     // If the "exitFrame" callback is not finished, abort it. 
     if (exitOperation.Status != DispatcherOperationStatus.Completed) 
     { 
      exitOperation.Abort(); 
     } 
    } 

    private static Object ExitFrame(Object state) 
    { 
     DispatcherFrame frame = state as DispatcherFrame; 

     // Exit the nested message loop. 
     frame.Continue = false; 
     return null; 
    } 
} 
+0

Vielen Dank! Das hat super funktioniert. Hätte wissen müssen, dass die Artikel zuerst "visualisiert" werden müssen! –

+0

Es scheint, dass offet.Y relativ ist, also myScroll.ScrollToVerticalOffset (offset.Y); muss geändert werden in sv.ScrollToVerticalOffset (offset.Y + sv.VerticalOffset); –

2

Jasons Scroll Trick ist eine gute Möglichkeit, einen TreeViewItem in eine bestimmte Position zu bewegen.

Ein Problem allerdings: In MVVM haben Sie im View-Modell keinen Zugriff auf den ScrollViewer. Hier ist ein Weg, um es trotzdem zu erreichen. Wenn Sie ein TreeViewItem haben, können Sie den visuellen Baum bis zum eingebetteten ScrollViewer hochgehen:

// Get the TreeView's ScrollViewer 
DependencyObject parent = VisualTreeHelper.GetParent(selectedTreeViewItem); 
while (parent != null && !(parent is ScrollViewer)) 
{ 
    parent = VisualTreeHelper.GetParent(parent); 
} 
Verwandte Themen