Treeview保持滚动位置

时间:2010-07-29 14:47:53

标签: winforms treeview

我有一个包含很多节点的Treeview。如果我切换节点,树视图的滚动条将设置在底部。

为了保持切换节点可见,我使用node.EnsureVisible()。但我不太喜欢这种方法,因为它让最终用户感到困惑。

所以我看得更远,现在我使用这里提供的代码:

Maintain scroll position of treeview

此代码的问题是,树视图的内容不会滚动。滚动条位于正确的位置,但内容不执行任何操作。在我点击滚动条(我不滚动)之前,内容变得可见。

所以,我想要实现的是当切换treenode时我想保持滚动位置。

切换节点的代码。在这种情况下,节点向下。功能如下所示:

// Check a node is selected
if (tvCategories.SelectedNode == null)
    return;

// The first node may not be moved
if (IsNewRootCategorySelected())
    return;

Point ScrollPos = GetTreeViewScrollPos(tvCategories);

// Declare and instantiate the parent node
TreeNodeCollection parent = null;
if (tvCategories.SelectedNode.Parent == null)
    parent = tvCategories.Nodes;
else
    parent = tvCategories.SelectedNode.Parent.Nodes;

TreeNode selectedNode = tvCategories.SelectedNode;
int index = selectedNode.Index;

// Check there's a next node at the same level
if (tvCategories.SelectedNode.NextNode == null)
{
    // Check if the parent node has a next node
    if (tvCategories.SelectedNode.Parent != null && tvCategories.SelectedNode.Parent.NextNode != null)
    {
        // get the destination parent
        TreeNode destParent = selectedNode.Parent.NextNode;

        // remove selected node from tree view
        parent[index].Remove();

        // If selected node is a category, add the node to the first index
        if (selectedNode.Tag is Category)
        {
            destParent.Nodes.Insert(0, selectedNode);
        }

        // If selected node is a question, add node below last category
        if (selectedNode.Tag is Question)
        {
            int newIndex = 0;

            // Loop through collection to find last category
            for (int i = destParent.Nodes.Count - 1; i >= 0; i--)
            {
                if (destParent.Nodes[i].Tag is Category)
                {
                    newIndex = i + 1;
                    break;
                }
            }

            destParent.Nodes.Insert(newIndex, selectedNode);
        }

        selectedNode.Expand();
    }
}
else
{
    // Switch nodes in same level

    tvCategories.BeginUpdate();
    _loading = true;

    if (selectedNode.Tag is Category)
    {
        // Only switch category downwards when next node is a catgory
        if (selectedNode.NextNode.Tag is Category)
        {
            // Perform switch
            TreeNode switchNode = parent[index + 1];

            parent[index + 1].Remove();
            parent[index].Remove();

            parent.Insert(index, switchNode);
            parent.Insert(index + 1, selectedNode);
        }
        else if (selectedNode.NextNode.Tag is Question)
        {
            // Make the switch to another node below
            if (selectedNode.Parent.NextNode != null)
            {
                // Parent is always a category

                TreeNode categoryParent = selectedNode.Parent.NextNode;

                // Remove selected node from current parent
                parent.Remove(selectedNode);

                // Insert selected node
                categoryParent.Nodes.Insert(0, selectedNode);

            }
        }
    }
    if (selectedNode.Tag is Question)
    {
        if (selectedNode.NextNode.Tag is Question)
        {
            // Perform switch
            TreeNode switchNode = parent[index + 1];

            parent[index + 1].Remove();
            parent[index].Remove();

            parent.Insert(index, switchNode);
            parent.Insert(index + 1, selectedNode);
        }
    }
}

tvCategories.EndUpdate();
// Set focus
tvCategories.Focus();

tvCategories.SelectedNode = selectedNode;
SetTreeViewScrollPos(tvCategories, ScrollPos);

1 个答案:

答案 0 :(得分:0)

using System.Runtime.InteropServices;

        [DllImport("user32.dll")]
        static public extern int SendMessage(
                IntPtr hWnd,    // HWND handle to destination window
                int Msg,     // UINT message
                int wParam,  // WPARAM first message parameter
                int lParam   // LPARAM second message parameter
                );

        public const int SB_LINEUP = 0;
        public const int SB_LINELEFT = 0;
        public const int SB_LINEDOWN = 1;
        public const int SB_LINERIGHT = 1;
        public const int SB_PAGEUP = 2;
        public const int SB_PAGELEFT = 2;
        public const int SB_PAGEDOWN = 3;
        public const int SB_PAGERIGHT = 3;
        public const int SB_THUMBPOSITION = 4;
        public const int SB_THUMBTRACK = 5;
        public const int SB_TOP = 6;
        public const int SB_LEFT = 6;
        public const int SB_BOTTOM = 7;
        public const int SB_RIGHT = 7;
        public const int SB_ENDSCROLL = 8;

        public const int WM_HSCROLL = 276;
        public const int WM_VSCROLL = 277;

        public void eZScroll(TreeView treeView, ArrowDirection direction, int numScrolls)
        {
            int Msg = 0;
            int wParam = 0;
            int lParam = 0;

            switch (direction)
            {
                case ArrowDirection.Up:
                    Msg = WM_VSCROLL;
                    wParam = SB_LINEUP;
                    break;
                case ArrowDirection.Down:
                    Msg = WM_VSCROLL;
                    wParam = SB_LINEDOWN;
                    break;
                case ArrowDirection.Left:
                    Msg = WM_HSCROLL;
                    wParam = SB_LINELEFT;
                    break;
                case ArrowDirection.Right:
                    Msg = WM_HSCROLL;
                    wParam = SB_LINERIGHT;
                    break;
            }

            for (int i = 0; i < numScrolls; i++)
            {
                SendMessage(treeView.Handle, Msg, wParam, lParam);
            }
        }

在以下地方粘贴:

public Form1()
{
    InitializeComponent();
}

这样打电话:

eZScroll(treeView1, ArrowDirection.Up, 1); 

我不确定这段代码是否可以直接使用,但我相信它能帮助您解决问题。