This is a migrated thread and some comments may be shown as answers.

Scroll Treeview so Expanded node is on top

9 Answers 923 Views
Treeview
This is a migrated thread and some comments may be shown as answers.
Ryan
Top achievements
Rank 1
Ryan asked on 14 Apr 2008, 11:26 PM
Basically I have a RadTreeView structure with a lot of sub nodes.  I want to bea ble to scroll the treeview when a node is expanded so that the expanded node is the top node.  Ive been trying to use ScrollIntoView without much success.

9 Answers, 1 is accepted

Sort by
0
Jordan
Telerik team
answered on 18 Apr 2008, 11:19 AM
Hi Ryan,

The current implementation of the ScrollIntoView method tries to scroll to the given node so that it is somewhere in the middle of the tree view control. However, this is not exactly the behavior that you need.

You could try implementing that behavior with the following steps:
  1. Get the first visible node with code like:
    (this.radTreeView1.TreeViewElement.Items[0] as TreeNodeUI).AssociatedTreeNode
  2. Then use a depth first traversal to find the position of the first visible node and of the node that you want to scroll to.
  3. Finally scroll the tree view control with the difference between the row positions
Hope this helps. I will follow up with some more code later.

Best wishes,
Jordan
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Jordan
Telerik team
answered on 07 May 2008, 11:51 AM
Hi Ryan,

Sorry about the delay in getting back to you. Here's an implementation of the approach I proposed in my previous email:

public class RadTreeViewScrollHelper 
    { 
        public static void ScrollToNode(Telerik.WinControls.UI.RadTreeView treeView, RadTreeNode node) 
        { 
            Telerik.WinControls.UI.RadTreeView.EnsureVisible(node); 
 
            RadTreeNode firstVisibleNode = (treeView.TreeViewElement.Items[0] as TreeNodeUI).AssociatedTreeNode; 
            int basePosition = RadTreeViewScrollHelper.GetPosition(treeView, firstVisibleNode); 
            int targetPosition = RadTreeViewScrollHelper.GetPosition(treeView, node); 
            int positionDelta = basePosition - targetPosition; 
            treeView.ScrollBy(positionDelta); 
        } 
 
        public static int GetPosition(Telerik.WinControls.UI.RadTreeView treeView, RadTreeNode targetNode) 
        { 
            int currentPosition = 0; 
 
            Stack<RadTreeNode> stack = new Stack<RadTreeNode>(); 
            RadTreeNode node = null
            int i; 
            for (i = treeView.Nodes.Count - 1; i > -1; i--) 
            { 
                node = treeView.Nodes[i]; 
                if (node.Visible) 
                { 
                    stack.Push(node); 
                } 
            } 
 
            while (stack.Count > 0) 
            { 
                node = stack.Pop(); 
                if (node == targetNode) 
                { 
                    return currentPosition; 
                } 
                currentPosition++; 
 
                if ((node.Nodes.Count > 0) && (node.Expanded)) 
                { 
                    for (i = node.Nodes.Count - 1; i > -1; i--) 
                    { 
                        if (node.Nodes[i].Visible) 
                        { 
                            stack.Push(node.Nodes[i]); 
                        } 
                    } 
                } 
            } 
 
            return -1; 
        } 
    } 

And you can use it as shown below:

private void button1_Click(object sender, EventArgs e) 
        { 
            RadTreeNode node = Telerik.WinControls.UI.RadTreeView.ExecuteScalarCommand(this.radTreeView1.Nodes, -1, 
                new FindNodeByTextCommand(), this.textBox1.Text) as RadTreeNode; 
            if (node == null
            { 
                return
            } 
 
            RadTreeViewScrollHelper.ScrollToNode(this.radTreeView1, node); 
        } 
 
        public class FindNodeByTextCommand : CommandBase 
        { 
            public override object Execute(params object[] settings) 
            { 
                if (settings.Length > 1 && this.CanExecute(settings[0])) 
                { 
                    RadTreeNode node = settings[0] as RadTreeNode; 
                    string text = (settings[1] as IList)[0] as string
 
                    if (node != null && !string.IsNullOrEmpty(text)) 
                    { 
                        if (node.Text == text) 
                        { 
                            return node; 
                        } 
                    } 
                } 
                return null
            } 
 
            public override bool CanExecute(object parameter) 
            { 
                if (parameter is RadTreeNode) 
                { 
                    return true
                } 
                return base.CanExecute(parameter); 
            } 
        } 

I hope this helps. If you have any further questions, please contact me.

Sincerely yours,
Jordan
the Telerik team

Instantly find answers to your questions at the new Telerik Support Center
0
Ryan
Top achievements
Rank 1
answered on 11 May 2008, 09:27 PM
Perfect Thank you guys again for all your work.
0
Marc
Top achievements
Rank 1
Veteran
answered on 03 Jun 2020, 08:33 AM

Is this still the solution after 12 years?

I want to see the expanded node fully, Microsoft TreeView is reposition after opening a node.

 

Regards

0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 04 Jun 2020, 05:48 AM
Hello, Marc, 

Usually, setting the RadTreeView.SelectedNode property is expected to navigate the view to this particular node. However, once the node gets into the visible nodes, the view is not scrolled any more even though the node may be at the bottom of the tree view. 

In order to simulate scrolling to the node in such a way that it is placed at the top, you can use the following code snippet which result is illustrated in the attached gif file. Note that this is just a sample approach and it may not cover all possible cases. Feel free to modify and extend in a way which suits your requirements best: 
        public RadForm1()
        {
            InitializeComponent();
            for (int i = 0; i < 50; i++)
            {
                RadTreeNode node = new RadTreeNode("Node"+i);
                this.radTreeView1.Nodes.Add(node);
                for (int j = 0; j < 5; j++)
                {
                    RadTreeNode subNode = new RadTreeNode("SubNode"+i+"."+j);
                    node.Nodes.Add(subNode);
                }
            }

            nodeToSelect = this.radTreeView1.Nodes[20];
        }

        RadTreeNode nodeToSelect;
        private void radButton1_Click(object sender, EventArgs e)
        {
            TreeNodeElement firstVisibleNode = this.radTreeView1.TreeViewElement.ViewElement.Children[0] as TreeNodeElement;
            if (firstVisibleNode != null)
            { 
                //move scrollbar from top to bottom
                while (firstVisibleNode.Data != nodeToSelect)  
                {
                    if (this.radTreeView1.TreeViewElement.VScrollBar.Value == (this.radTreeView1.TreeViewElement.VScrollBar.Maximum - this.radTreeView1.TreeViewElement.VScrollBar.LargeChange - 1))
                    {
                        break;
                    }
                    this.radTreeView1.TreeViewElement.VScrollBar.Value = Math.Min((this.radTreeView1.TreeViewElement.VScrollBar.Value + 1),
                        (this.radTreeView1.TreeViewElement.VScrollBar.Maximum - this.radTreeView1.TreeViewElement.VScrollBar.LargeChange - 1));
                    Application.DoEvents();
                    firstVisibleNode = this.radTreeView1.TreeViewElement.ViewElement.Children[0] as TreeNodeElement;
                }

                if (firstVisibleNode.Data != nodeToSelect)
                {
                    //move scrollbar from bottom to top
                    while (firstVisibleNode.Data != nodeToSelect)  
                    {
                        if (this.radTreeView1.TreeViewElement.VScrollBar.Value == 0)
                        {
                            break;
                        }
                        this.radTreeView1.TreeViewElement.VScrollBar.Value = Math.Max((this.radTreeView1.TreeViewElement.VScrollBar.Value - 1), 0);
                        Application.DoEvents();
                        firstVisibleNode = this.radTreeView1.TreeViewElement.ViewElement.Children[0] as TreeNodeElement;
                        this.radTreeView1.TreeViewElement.EnsureVisible(firstVisibleNode.Data);
                    }
                }
                nodeToSelect.Expand();
            } 
        }
I hope this information helps. If you need any further assistance please don't hesitate to contact me.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Patrick
Top achievements
Rank 1
commented on 08 Dec 2022, 06:15 PM | edited

Auto-scrolling can be visibly very slow when there are hundreds or thousands of nodes, and there's a customized approach to formatting each node.

A few minor changes make things move quicker in my situation.

Before starting the loop:

nodeToSelect.Selected = true;
nodeToSelect.EnsureVisible();
Application.DoEvents();

Increase and decrease the VScrollBar.Value not by 1 but by the node's height as in:

this.radTreeView1.TreeViewElement.VScrollBar.Value = Math.Max((this.tvwWBS.TreeViewElement.VScrollBar.Value - firstVisibleNode.ItemHeight), 0);

0
Marc
Top achievements
Rank 1
Veteran
answered on 04 Jun 2020, 05:59 AM

Hello Dess,

why is this so complicatet?

I just want the standard from Microsoft TreeView.

You can see it in the gif. Left Telerik, right Microsoft.

Regards

0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 04 Jun 2020, 09:52 AM

Hello, Marc,

The provided gif file is greatly appreciated. Indeed, it illustrates different scrolling behavior.

However, I would like to note that RadTreeView and MS TreeView are two different controls with their internal specific implementation. Hence, even though we strive to follow the basic functionality that the standard WinForms controls offer, sometimes it is expected to have some differences like with the tree view scrolling.

It seems to be a reasonable request. That is why I have logged it in our feedback portal by creating a public thread on your behalf. You can track its progress, subscribe for status changes and add your comments on the following link - feedback item.

I have also updated your Telerik points.

Feel free to use the previously suggested approach which seems to achieve the desired behavior. It can be executed in the NodeExpandedChanged event as well.

Should you have further questions please let me know.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Harish
Top achievements
Rank 1
Veteran
answered on 23 Jul 2020, 10:26 AM

Hi,

I am facing similar issue with WPF, is the issue fixed so that I can update my telerik dll's.

0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 23 Jul 2020, 10:44 AM

Hello, Harish,

I would like to note that this forum is related to the Telerik UI for WinForms suite. If you are experiencing any difficulties with the WPF tree view, feel free to post your question in the relevant forum: https://www.telerik.com/forums 

As to the question at hand, the status "Unplanned" of the feedback item indicates that it is still not addressed. Make sure that you cast your vote for it in order to increase its priority. I would recommend you to click the "Follow" button of this item. Thus, you will get notified once any status changes occur. 

Should you have further questions regarding the Telerik UI for WinForms suite please let me know.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Tags
Treeview
Asked by
Ryan
Top achievements
Rank 1
Answers by
Jordan
Telerik team
Ryan
Top achievements
Rank 1
Marc
Top achievements
Rank 1
Veteran
Dess | Tech Support Engineer, Principal
Telerik team
Harish
Top achievements
Rank 1
Veteran
Share this question
or