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

problem with ContainerFromItemRecursive

1 Answer 44 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Dejan
Top achievements
Rank 1
Dejan asked on 24 Nov 2011, 09:49 AM

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.


1 Answer, 1 is accepted

Sort by
0
Petar Mladenov
Telerik team
answered on 29 Nov 2011, 09:08 AM
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 >>

Tags
TreeView
Asked by
Dejan
Top achievements
Rank 1
Answers by
Petar Mladenov
Telerik team
Share this question
or