简体   繁体   English

在滚动视图中滚动到选定的Treeviewitem

[英]Scrolling to selected Treeviewitem within a scrollview

I have a scrollviewer wrapping a treeview. 我有一个滚动浏览器包装树视图。

I populate the treeview programmatically (it is not bound), and expand the treeview to a predetermined treeviewitem. 我以编程方式填充树视图(未绑定),并将树视图扩展为预定的treeviewitem。 That all works fine. 一切正常。

My problem is that when the tree expands I would like the scrollview that parents the treeview to scroll to the treeviewitem that I just expanded. 我的问题是,当树扩展时,我希望将树视图作为父级的滚动视图滚动到我刚刚扩展的treeviewitem。 Any ideas? 有任何想法吗? - keep in mind that the treeview may not have the same structure each time it is expanded, so that rules out just storing the current scroll position and reseting to that... -请记住,树形视图在每次扩展时可能不会具有相同的结构,因此排除了仅存储当前滚动位置并重置为该位置的可能性。

I've had the same issue, with the TreeView not scrolling to the selected item. 我遇到了同样的问题,TreeView没有滚动到所选项目。

What I did was, after expanding the tree to the selected TreeViewItem, I called a Dispatcher Helper method to allow the UI to update, and then used the TransformToAncestor on the selected item, to find its position within the ScrollViewer. 我所做的是,在将树扩展到选定的TreeViewItem之后,我调用了Dispatcher Helper方法以允许UI更新,然后对选定的项目使用TransformToAncestor,以找到其在ScrollViewer中的位置。 Here is the 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);

Here is the DispatcherHelper code: 这是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;
    }
}

Jason's ScrollViewer trick is a great way of moving a TreeViewItem to a specific position. Jason的ScrollViewer技巧是将TreeViewItem移动到特定位置的好方法。

One problem, though: in MVVM you do not have access to the ScrollViewer in the view model. 但是,存在一个问题:在MVVM中,您无权访问视图模型中的ScrollViewer。 Here is a way to get to it anyway. 无论如何,这是一种方法。 If you have a TreeViewItem, you can walk up its visual tree until you reach the embedded ScrollViewer: 如果您有TreeViewItem,则可以沿着它的可视树移动,直到到达嵌入式ScrollViewer:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM