/// <summary> /// Computes the next visible TreeViewItem in order from top to bottom. /// Wraps around when it gets to the bottom-most item. /// </summary> /// <param name="treeViewItem">The starting item.</param> /// <returns>The next item in the traversal.</returns> private static TreeViewItem NextVisibleTreeViewItem(TreeViewItem treeViewItem) { // First child if (treeViewItem.IsExpanded && treeViewItem.HasItems && treeViewItem.Items.Count > 0) { return(treeViewItem.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem); } while (true) { var parent = treeViewItem.FindVisualAncestor <TreeViewItem>(); ItemContainerGenerator itemContainerGenerator; if (parent == null) { var treeView = treeViewItem.FindVisualAncestor <TreeView>(); itemContainerGenerator = treeView.ItemContainerGenerator; } else { itemContainerGenerator = parent.ItemContainerGenerator; } var childIndex = itemContainerGenerator.IndexFromContainer(treeViewItem); if (childIndex >= 0 && (childIndex + 1) < itemContainerGenerator.Items.Count) { // Next sibling return(itemContainerGenerator.ContainerFromIndex(childIndex + 1) as TreeViewItem); } // No more siblings if (parent == null) { // Reached the end. Start at the top again. return(itemContainerGenerator.ContainerFromIndex(0) as TreeViewItem); } // Go to the parent and find its next sibling. treeViewItem = parent; } }