public void GenerateCollectionsRecursive() { List <ModelTreeItem> newNodes = new List <ModelTreeItem>(); { // Identify collections by separator characters. var collectionGroups = ChildItems.GroupBy(c => { int indexOfSeparator = c.Text.IndexOfAny(_CollectionSeparators); if (indexOfSeparator > 0) { return(c.Text.Substring(0, indexOfSeparator)); } return(string.Empty); }); foreach (var group in collectionGroups) { if (group.Count() > 1 && group.Key != string.Empty) { // Locate the full collection name within the items text. int originalSeparatorIndex = group.Key.Length; int refinedSeparatorIndex = originalSeparatorIndex; while (true) { if (group.First().Text.Length < refinedSeparatorIndex) { break; } int newSeparatorIndex = group.First().Text.IndexOfAny(_CollectionSeparators, refinedSeparatorIndex + 1); if (newSeparatorIndex > refinedSeparatorIndex) { string newPrefix = group.First().Text.Substring(0, newSeparatorIndex); if (group.Any(t => t.Text.Length < newSeparatorIndex || t.Text.Substring(0, newSeparatorIndex) != newPrefix)) { break; } refinedSeparatorIndex = newSeparatorIndex; } else { break; } } string newCollectionKey = originalSeparatorIndex != refinedSeparatorIndex?group.First().Text.Substring(0, refinedSeparatorIndex) : group.Key; // Virtualize collection, except if the name matches with this node. if (this.Text != newCollectionKey) { newNodes.Add(this.VirtualizeChildrenByTextPrefix(newCollectionKey, newCollectionKey)); } } } } foreach (var child in ChildItems.Where(c => !newNodes.Contains(c))) { child.GenerateCollectionsRecursive(); } }