How do I get the RadTreeViewItem if I'm using HierarchicalDataTemplate?

8 posts, 1 answers
  1. Luis
    Luis avatar
    6 posts
    Member since:
    Apr 2009

    Posted 10 Apr 2009 Link to this post

    I have a RadTreeView with HierarchicalDataTemplate as follows:

    <HierarchicalDataTemplate DataType="Category" ItemsSource="{Binding XPath=Category}"
       <TextBlock x:Name="tbCategoryName" Text="{Binding XPath=@Name}" MouseRightButtonUp="tbCategoryName_MouseRightButtonUp" 
                               MouseDown="tbCategoryName_MouseDown"
       </TextBlock> 
    </HierarchicalDataTemplate> 

    I need access to the RadTreeViewItem so that I can call methods and properties such as BeginEdit, ExpandAll, and IsExpanded.
    This is my RadTreeView declaration:

            <telerik:RadTreeView ItemsSource="{Binding Source={StaticResource CategoriesXML}}" Margin="105,64,0,0"  
                                 Name="tvOntology" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" 
                                 IsEditable="True" IsEnabled="True" IsExpandOnDblClickEnabled="False"  
                                 IsExpandOnSingleClickEnabled="True"
            </telerik:RadTreeView> 
     
    It works fine but I'm not able to get the RadTreeViewItem. Could someone tell me how, please?
  2. Mike
    Mike avatar
    26 posts
    Member since:
    Jun 2008

    Posted 10 Apr 2009 Link to this post

    Hi Luis

    from where do you need the access? if it is from your mouselistener then you may try this:

    object item = myTreeView.SelectedItem;
    RadTreeViewItem tvi = myTreeView.ContainerFromItemRecursive(item); 

    Greez Mike


  3. UI for WPF is Visual Studio 2017 Ready
  4. Luis
    Luis avatar
    6 posts
    Member since:
    Apr 2009

    Posted 12 Apr 2009 Link to this post

    I was trying to access it from other events. I managed to do it with ChildrenOfType<RadTreeViewItem>(). Your post did help though, thanks.
  5. Luis
    Luis avatar
    6 posts
    Member since:
    Apr 2009

    Posted 12 Apr 2009 Link to this post

    I'm still having a hard time getting the RadTreeViewItem's.

    myTreeView.ChildrenOfType<RadTreeViewItem>(); only returns the root item and I can't get any further by any means.

    Is there a way to itereate through the RadTreeViewItem's?

    Thanks.
  6. Answer
    Ivan
    Admin
    Ivan avatar
    519 posts

    Posted 14 Apr 2009 Link to this post

    Hi Luis,

    Please preview the How do I get the RadTreeViewItem article where accessing the RadTreeViewItem is demonstrated.

    Hope this information helps.

    All the best,
    Ivan
    the Telerik team

    Check out Telerik Trainer , the state of the art learning tool for Telerik products.
  7. Tim
    Tim avatar
    169 posts
    Member since:
    Apr 2008

    Posted 06 Aug 2009 Link to this post

    foreach (RadTreeViewItem item in Renderer.ChildrenOfType<RadTreeViewItem>()) 
        // item is an in-order traversal of the tree, but only those nodes 
        // which have been previously or explicitly visited. 
     





    Given the above, I want to compare each (item.Item as MyObject).Property to some other object's property.  If I have not yet expanded a given node, it's children do not show up.  How come?  If I expand them first (and collapse them) then they appear in the loop.

    It must have to do with when the items are prepared.  The problem is that I am trying to attach a double click from a RadGridView's row to a specific item in the tree, but if that node has not yet been opened, I can't find it (I wish to keep the navigation in sync regardless of the double-click-in-a-Grid or click-on-a-tree-node method chosen).

    Can I force the tree to always pre-prepare items?  Is there a better way?  Can I ask each item to prepare its children?  I doin't want to expand the whole tree for sure.

    Thx,
    Tim

  8. Ivan
    Admin
    Ivan avatar
    519 posts

    Posted 12 Aug 2009 Link to this post

    Hi Luis,

    The virtualization (i.e. creation / non-creation) of the item containers is by design - this is the feature of the Silverlight Framework. As a small demonstration we prepared (and attached here) an example. Below is its description:

        Attached example file: ContainerFromItemRecursive.zip

    In order to get container below the first level you can try the RadTreeView.ContainerFromItemRecursive() method. But please be aware of the following. If your tree items are data bound (via ItemsSource) some of their containers (RadTreeViewItem) appeared not constructed (until you expand their branches). For example in the attached project there is a three level tree. After the page loads you can see only first level items and really only their containers are constructed. If you click the "Select my Favorite Item" nothing will happens (until you expand the tree). After you expand the tree (press the "Expand the Tree" button) you can get the container of the "Favorite Item" (the item at the "bottom" of the tree).

    Note: You mentioned comparison of items of MyObject type. Because of this I had realized you want to deal with the data items (but not with items' containers). In this case you can get them via your data source. But once again accessing to the item's container depends on its existence (i.e. is it created).


    As I found the other aspect from your post is related to the SelectedItem synchronization. Below we will try to explain the case:

        Attached example file: Binding to SelectedItem.zip

    Currently the SelectedValue, the SelectedItem and the SelectedItems properties have only getters. Even more the SelectedItem returns the first item from the SelectedItems collection. Because of this you can not bind to it. But if you try the attached example you will (probably) find a way to workaround the case. Below is a short description of the workaround:
    • In general there are two synchronized RadTreeViews. For more information please visit the following blog post: Simulating IsSynchronizedWithCurrentItem in Silverlight.
       
    • In order to accomplish SelectedItem binding you have to add some additional extensions:
      1. Add some extensions classes to your application as shown in the sample application.
         
      2. Add an additional attached property:
         
        public static readonly DependencyProperty IsSynchronizedWithCurrentItemProperty = 
            DependencyProperty.RegisterAttached("IsSynchronizedWithCurrentItem"
                typeof(bool), 
                typeof(SelectorExtension), 
                new PropertyMetadata(false, (s, e) => 
            var control = s as RadTreeView; 
            if (control == null
            { 
                return
            } 
            if (control.ItemsSource != null
            { 
                if ((bool)e.NewValue) 
                { 
                    SetBinding(control, control.ItemsSource as IObservableCollectionEx); 
                } 
                return
            } 
            if ((bool)e.NewValue) 
            { 
                control.SelectionChanged += new SelectionChangedEventHandler(control_SelectionChanged); 
                _selectors.Add(control); 
            } 
            else 
            { 
                if (_selectors.Contains(control)) 
                { 
                    _selectors.Remove(control); 
                } 
            } 
        })); 
         
      3. Subscribe to SelectionChanged:
         
        control.SelectionChanged += 
            new SelectionChangedEventHandler(control_SelectionChanged); 
         
      4. Add the desired code in the SelectionChanged  handler:
         
        static void control_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e) 
            ... 
            //Add the desired functionality here 
            SetBinding(control, source.SelectedObject); 
            ... 
         
        where:
         
        private static void SetBinding(RadTreeView control, object source) 
            if (control.ItemContainerGenerator.ContainerFromItem(source) != null
            { 
                (control.ItemContainerGenerator.ContainerFromItem(source) as RadTreeViewItem).IsSelected = true
            } 
         
      5. After you have done all explained in the previous steps set the attached property in XAML:
         
        <telerik:RadTreeView 
            ItemTemplate="{StaticResource DataTemplate1}" 
            ItemsSource="{Binding Items}" 
            local:SelectorExtension.IsSynchronizedWithCurrentItem="True" /> 
         



    As a force creation of tree items you can rely on the ExpandAll method (preview the first example), but it still expands the tree visually. Recently we implement two new methods that may help you to find an appropriate solution: GetItemByPath and ExpandItemByPath. We advise you to try them too.

    Sincerely yours,
    Ivan
    the Telerik team

    Check out Telerik Trainer , the state of the art learning tool for Telerik products.
  9. Tim
    Tim avatar
    169 posts
    Member since:
    Apr 2008

    Posted 14 Aug 2009 Link to this post

    Ivan,

    ExpandItemByPath does the trick.  Luckily I have the container hierarchy handy so I can specify the node I want and its ancestors.

    Tim
Back to Top
UI for WPF is Visual Studio 2017 Ready