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

Selecting Nodes in Code

5 Answers 299 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Dave
Top achievements
Rank 1
Dave asked on 29 Sep 2009, 06:27 PM

I am using the RadTreeView control and I want to Select a node in the code behind.   I have looked at the previous post on this topic and none of the suggestions worked. Here is the code I am using to get the item:


RadTreeViewItem item = _myTree.ContainerFromItemRecursive(doc) as RadTreeViewItem;  

When I am through I want my tree to look like this:

-          Org

o   Folder1

§  SubFolder1

·         Doc 1(SELECTED)

·         Doc2

§  SubFolder2

o   Folder2

o   Folder3

o   Folder4

 

My item is null after the call to ContainerFromItemRecursive.   I already have the tree expanding to the folder level. 

 

 

 

 

 

 

 

 


5 Answers, 1 is accepted

Sort by
0
Kiril Stanoev
Telerik team
answered on 01 Oct 2009, 11:53 AM
Hi Dave,

I assume the node you are trying to select is not visible(its parent is not expanded).
If this is the case, the you have to make the node visible first. To do that, you can use the ExpandItemByPath method of RadTreeView. The ExpandItemByPath takes 2 arguments: the full path to the node and a separator.
Assume the following ViewModel:



Every Person, Department and Organization has a name(represented by a string property Name).
Imagine you are looking for a person called "John", who is in the "Silverlight Department", which is part of "Microsoft". The most basic way this can be done is via 3 foreach loops:

public Employee FindEmployee(string name) 
    Employee targetEmployee = null
 
    foreach (Organization organization in this.Items) 
    { 
        foreach (Department department in organization.Departments) 
        { 
            foreach (Employee employee in department.Employees) 
            { 
                if (employee.Name == name) 
                { 
                    targetEmployee = employee; 
                    string path = string.Format("{0}|{1}|{2}", organization.Name, department.Name, employee.Name); 
                    targetEmployee.FullPath = path; 
                    break
                } 
            } 
            if (targetEmployee != null
            { 
                break
            } 
        } 
        if (targetEmployee != null
        { 
            break
        } 
    } 
    return targetEmployee; 

As you can see, as soon as there is a match between the employee we are looking for and the current employee, the method also creates a full path to this employee by taking the name of the organization, department and employee separated by "|".

Once constructed, the full path can be used to select the container of the item:

private void Button_Click(object sender, RoutedEventArgs e) 
    Employee emp = (treeView.ItemsSource as OrganizationsDataSource).FindEmployee("John"); 
    treeView.ExpandItemByPath(emp.FullPath, "|"); 
    treeView.ContainerFromItemRecursive(emp).IsSelected = true

I am attaching my sample project for further reference. Have a look at it and if you have additional questions, let me know.

All the best,
Kiril Stanoev
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Dave
Top achievements
Rank 1
answered on 01 Oct 2009, 06:13 PM
Thanks for the demo.  This is getting closer to what I need.  I two questions:

1)  How do I expand to the "Scott Guthrie" node without user interaction?  In other words at what point in the page loading lifecycle is it safe to call the code to select the item.  I have tried after the InitializeComponent() call in the page constructor, in the call back method of the page Loaded event, and the call back method of the tree loaded event.  Each time the treeView.ContainerFromItemRecursive(emp).IsSelected = true;  line of code is called it throw an exception that the ContainerFromItemRecursive call is null.

2)  If I don't want to have the Name property be the property for building the path how do I do that?  I have tried setting this
 

telerikCore

 

:TextSearch.TextPath="Path" on treeview control.  I want to use a property called "Path".

Thanks

Dave

 

0
Kiril Stanoev
Telerik team
answered on 02 Oct 2009, 12:41 PM
Hi Dave,

1) The reason why the item you want to expand is null is because the treeview items have not been generated yet. That is why you will need to use a Dispatcher. Simply attach to the MainPage's Loaded event and execute the same logic using a dispatcher.

public MainPage() 
    InitializeComponent(); 
    Loaded += new RoutedEventHandler(MainPage_Loaded); 
 
void MainPage_Loaded(object sender, RoutedEventArgs e) 
    Dispatcher.BeginInvoke(new Action(() => 
    { 
        Employee emp = (treeView.ItemsSource as OrganizationsDataSource).FindEmployee("Scott Guthrie"); 
        treeView.ExpandItemByPath(emp.FullPath, "|"); 
        treeView.ContainerFromItemRecursive(emp).IsSelected = true
    })); 

2) In the override ToString method of each business object (Employee, Department and Organization) you will have to return not the Name property, as it is now, but you Path property;

public class Organization : INotifyPropertyChanged 
    // Code ommited 
 
    public string Path {getset; } 
 
    public override string ToString() 
    { 
        return this.Path; 
    } 

Also, you will have to modify your FindEmployee method a little bit.

if (employee.Name == name) 
    targetEmployee = employee; 
    string path = string.Format("{0}|{1}|{2}", organization.Path, department.Path, employee.Path); 
    targetEmployee.FullPath = path; 
    break

Let me know if you have additional questions.


Kind regards,
Kiril Stanoev
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
Dave
Top achievements
Rank 1
answered on 02 Oct 2009, 02:02 PM
This is what I needed.  Thanks
0
Manny
Top achievements
Rank 1
answered on 11 Dec 2009, 05:51 PM
Hi, I found this post while trying to figure out how to get RadComboBox to work with RadTreeView as template (found the blog on that and started from it). The issue I ran into with RadComboBox was that I couldn't get it to accept keyboard input when the RadTreeView was templated to popup. Bummer. So I started attaching keyup / keydown events to the combobox *and* the treeview and rolling my own--when the user starts typing in a string, look for the first matching item in the tree and auto-select that item without making the treeview go away. It works nice but I have to be able to find the typed item in the RadTreeView and auto-select it. Which led to this post and using the problematic ExpandItemByPath API.

Problematic is the word because, when I am trying to expand down multiple levels, a NULL pointer can be thrown. In my testing I found a good way to make this happen very quickly but I'm building a whole project for this to submit to Teleik, I'm late on this project as it is. So here are my notes for the next person to run into this problem:

    /// <summary>  
    /// First bug to solve--NULL pointer when expanding arbitrarily  
    /// deep into RadTreeView.  
    /// </summary>  
    /// <remarks>  
    /// Our use case:  
    /// <example>  
    ///   Currently expanded node: "1|2|3"  
    ///   Trying to expand to: "1|2|3|4|5"  
    /// </example>  
    ///     
    /// In the above example, RadTreeView throws NULL exception:  
    /// <code>  
    ///    at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData)  
    ///    at MS.Internal.XcpImports.MethodEx(DependencyObject obj, String name)  
    ///    at MS.Internal.XcpImports.UIElement_UpdateLayout(UIElement element)  
    ///    at System.Windows.UIElement.UpdateLayout()  
    ///    at Telerik.Windows.Controls.RadTreeView.GetItemByPath(String path, String separator)  
    ///    at Telerik.Windows.Controls.RadTreeView.ExpandItemByPath(String path, String separator)  
    ///    at Telerik.Windows.Controls.RadTreeView.ExpandItemByPath(String path)  
    ///    at ArchG2.Sl.Prog01.MainPage._trackedCboText_TextChanged(Object sender, EventArgs e)  
    /// </code>  
    ///   
    /// The issue appears to be timing related. In the case where the  
    /// exception occurs, it only occurs when navigating programmatically  
    /// down multiple levels from the currently expanded node *and* when  
    /// the parents of the embedded child node themselves expand to a  
    /// number of items (not many, but a few dozen). When we expand nodes  
    /// manually (by using the UI and expanding each parent) the exception  
    /// never occurs.  
    ///   
    /// Our first cut of workaround is to walk the path and expand each  
    /// node separately with an explicit call to UpdateLayout in between  
    /// each level. Not sure if this really solves the underlying issue  
    /// (assuming that it is timing-related based on expanding multiple  
    /// node levels where the nodes have not had time to populate). If  
    /// we still run into the problem then we'll modify this method to  
    /// start a new thread to run the expansions in, with a delegate to  
    /// allow the consumer to be notified when the expansions have (safely)  
    /// completed.  
    ///   
    /// For future: We should start at the top (root) and get the container.  
    /// See if the container is expanded. If not, fire off the expansion and  
    /// then wait for the container to be fully expanded command to expand and  
    /// then wait for the container (use <code>IsLoadingOnDemand</code> and  
    /// <code>IsLoadingOnDemandEnabled</code> to help track this). Then  
    /// locate the next node (using <code>ContainerFromItemRecursive</code>) and  
    /// repeat until we reach our child node. In that case, we don't actually  
    /// need to use the <code>ExpandItemByPath</code> API call.  
    /// </remarks>  
    /// <param name="fullPath">The full path of the node to locate</param>  
    /// <param name="separator">The separator to use</param>  
    public void SafeExpandItemByPath(string fullPath, string separator)  
    {  
      string[] paths = fullPath.Split(new string[] { separator }, StringSplitOptions.None);  
      System.Text.StringBuilder sb = new System.Text.StringBuilder(fullPath.Length);  
      foreach (string path in paths)  
      {  
        sb.Append(path);  
        _treeView.ExpandItemByPath(sb.ToString());  
        _treeView.UpdateLayout();  
        sb.Append(separator);  
      } //foreach  
    } //SafeExpandItemByPath  
 
Tags
TreeView
Asked by
Dave
Top achievements
Rank 1
Answers by
Kiril Stanoev
Telerik team
Dave
Top achievements
Rank 1
Manny
Top achievements
Rank 1
Share this question
or