problem with ContainerFromItemRecursive

2 posts, 0 answers
  1. Dejan
    Dejan avatar
    5 posts
    Member since:
    Oct 2011

    Posted 24 Nov 2011 Link to this post

    HI all,

     

    I’m using RadTreeView control for selecting fragments of hierarchical data.

    Under some circumstances amount of data is huge so I implemented filtering.

     

    Each time when filtering is performed (TextBox content for filtering is changed) new hirarachical structure is created and assigned to RadTreeView and all items are expanded:


    private void FilterTextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
    {
        string filterString = FilterTextBox.Text;
        //change datasource to filtered structure. 
        CourseContentTreeView.ItemsSource = LearningThemeAndObjectEntityTree.CreateLearningThemeAndObjectEntityStructure(CourseContent, filterString);
        CourseContentTreeView.ExpandAll();
    }

    Challenge starts here.

    If user selects (checked check box next to one node) several items and do some filtering - if items are not shown their selection is lost.

    In order to prevent that I create local structure which holds selected items and method which will reselect desired items once when they became visible.


    private void RecheckSelectedObjects()
    {
        CourseContentTreeView.Checked -= CourseContentTreeView_Checked;
      
        foreach (var item in CourseContentTreeView.Items)
        {
            // have to find the related treeViewItem
            var learningThemeAndObject = item as LearningThemeAndObjectEntityTree;
            RecheckItemRecursivelly(learningThemeAndObject);
        }
      
        CourseContentTreeView.Checked += CourseContentTreeView_Checked;
    }
      
    private void RecheckItemRecursivelly(LearningThemeAndObjectEntityTree learningThemeAndObject)
    {
        foreach (var selectedLo in SelectedCourseContents)
        {
            if (selectedLo.Id == learningThemeAndObject.Id)
            {
                var radTreeViewItem = FindContainerByItemId(learningThemeAndObject.Id);
                if (radTreeViewItem != null)
                {
      
                    radTreeViewItem.CheckState = ToggleState.On;
                }
            }
        }
      
        if (learningThemeAndObject.SubLearningThemeAndObjects != null)
        {
            foreach (var subItem in learningThemeAndObject.SubLearningThemeAndObjects)
            {
                RecheckItemRecursivelly(subItem);
            }
        }
    }

    The question is: when to invoke this method?

    If I do it immediately after CourseContentTreeView.ExpandAll();none of items is reselected because their containers are not found by FindContainerByItemId(learningThemeAndObject.Id); which sounds logical because most probably they are not drawn yet.

     

    To overcome this I put RecheckSelectedObjects()call in handler:


    private void CourseContentTreeView_Expanded(object sender, RadRoutedEventArgs e)
    {
        RecheckSelectedObjects();
    }

    This works but only partially. All items are reselected except items from last edge in the tree.

    Reason for this is because container for item in last edge is not found in FindContainerByItemId(learningThemeAndObject.Id);

    private RadTreeViewItem FindContainerByItemIdRecursivelly(LearningThemeAndObjectEntityTree currentItem, Guid itemId)
    {
        if (currentItem.SubLearningThemeAndObjects != null)
        {
            foreach (var subitem in currentItem.SubLearningThemeAndObjects)
            {
                if (subitem.Id == itemId)
                {
                    //todo dkos 20111123 this line of code makes us troubles.
                    //todo it is not possible to find container if item is in last displayed edge
                    return CourseContentTreeView.ContainerFromItemRecursive(subitem);
                }
                else
                {
                    var result = FindContainerByItemIdRecursivelly(subitem, itemId);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
        }
        return null;
    }

    Seems that even event Expanded is fired before containers of items are actually drawn on display.

                                                                                                                                                                                                               

    So my question would be: when to invoke my method RecheckSelectedObjects() and to be sure that all containers are displayed?

     

    Any idea?

     

    Thanks in advance!

    Dejan Kostic.


  2. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 29 Nov 2011 Link to this post

    Hello Dejan,

     First of all, I assume when you say "selection" and "select" , you mean "check operation" and "check". Then I see that you use databinding since you use the ItemsSource collection of the RadTreeView. As I managed to understand the main problem is that when re-assign the ItemsSource with its subset (sub-hierarchy, filtered hierarchy) some of the RadTreeViewItems have lost their CheckState. In such situations, the best approach is to introduce boolean property in your ViewModel and bind it to the CheckedState property of the RadTreeViewItem via ContainerBindings and converters. This way when filtering the ItemsSource and re-generating the containers ( the RadTreeViewItems ) the binding will take the previously saved boolean value from the ViewModel. Could this fit in your scenario instead of code-behind solution ?

    Greetings,
    Petar Mladenov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
Back to Top