2009-12-17 15 views
5

Tengo un scrollviewer que envuelve una vista de árbol.Desplazamiento a Treeviewitem seleccionado dentro de una vista de desplazamiento

Rellenar la vista de árbol mediante programación (no está enlazado), y expandir la vista de árbol a un elemento de vista de árbol predeterminado. Eso todo funciona bien.

Mi problema es que cuando el árbol se expande me gustaría que la vista de desplazamiento que los padres de la vista de árbol para desplazarse a la treeviewitem que acabo de ampliar. ¿Algunas ideas? - Tenga en cuenta que la vista de árbol puede no tener la misma estructura cada vez que se expande, por lo que descarta almacenar la posición de desplazamiento actual y restablecer a esa ...

Respuesta

4

He tenido el mismo problema, con el TreeView no se desplaza al elemento seleccionado.

Lo que hice fue, después de expandir el árbol al TreeViewItem seleccionado, invocar un método Dispatcher Helper para permitir que la UI se actualizara, y luego usé TransformToAncestor en el elemento seleccionado, para encontrar su posición dentro del ScrollViewer. Aquí está el código:

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

Aquí está el código DispatcherHelper:

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

¡Gracias! Eso funcionó muy bien. ¡Debería haber sabido que los artículos necesitaban ser "visualizados" primero! –

+0

Parece que offet.Y es relativo, por lo que myScroll.ScrollToVerticalOffset (offset.Y); necesita ser cambiado a sv.ScrollToVerticalOffset (offset.Y + sv.VerticalOffset); –

2

truco ScrollViewer de Jason es una gran manera de mover un TreeViewItem a una posición específica.

Un problema, sin embargo: en MVVM no tiene acceso al ScrollViewer en el modelo de vista. Aquí hay una manera de llegar a ella de todos modos. Si tiene un TreeViewItem, puede subir su árbol visual hasta llegar al ScrollViewer incrustado:

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