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.