// ****************************************************************** /// <summary> /// You cannot rely on this method to be synchronous. If you have any action that depend on the TreeViewItem /// (last item of collectionOfRootToNodePath) to be visible, you should set it in the 'onTreeViewItemVisible' method. /// This method should work for Virtualized and non virtualized tree. /// The difference with ExpandItem is that this one open up the tree up to the target but will not expand the target itself, /// while ExpandItem expand the target itself. /// </summary> /// <param name="treeView">TreeView where an item has to be set visible</param> /// <param name="listOfRootToNodePath">Any collectionic List. The collection should have every objet of the path to the targeted item from the root /// to the target. For example for an apple tree: AppleTree (index 0), Branch4, SubBranch3, Leaf2 (index 3)</param> /// <param name="onTreeViewVisible">Optionnal</param> public static void SetItemHierarchyVisible(this TreeView treeView, IEnumerable <object> listOfRootToNodePath, OnTreeViewVisible onTreeViewVisible = null) { ItemContainerGenerator icg = treeView.ItemContainerGenerator; if (icg == null) { return; // Is tree loaded and initialized ??? } SetItemHierarchyVisible(icg, new List <object>(listOfRootToNodePath), onTreeViewVisible); }
// ****************************************************************** private static void SetItemHierarchyVisible(ItemContainerGenerator icg, IList listOfRootToNodeItemPath, OnTreeViewVisible onTreeViewVisible = null) { Debug.Assert(icg != null); if (icg != null) { if (listOfRootToNodeItemPath.Count == 0) // nothing to do { return; } TreeViewItem tvi = icg.ContainerFromItem(listOfRootToNodeItemPath[0]) as TreeViewItem; if (tvi != null) // Due to threading, always better to verify { listOfRootToNodeItemPath.RemoveAt(0); if (listOfRootToNodeItemPath.Count == 0) { if (onTreeViewVisible != null) { onTreeViewVisible(tvi); } } else { if (!tvi.IsExpanded) { tvi.IsExpanded = true; } SetItemHierarchyVisible(tvi.ItemContainerGenerator, listOfRootToNodeItemPath, onTreeViewVisible); } } else { ActionHolder actionHolder = new ActionHolder(); EventHandler itemCreated = delegate(object sender, EventArgs eventArgs) { var icgSender = sender as ItemContainerGenerator; tvi = icgSender.ContainerFromItem(listOfRootToNodeItemPath[0]) as TreeViewItem; if (tvi != null) // Due to threading, it is always better to verify { SetItemHierarchyVisible(icg, listOfRootToNodeItemPath, onTreeViewVisible); actionHolder.Execute(); } }; actionHolder.Action = new Action(() => icg.StatusChanged -= itemCreated); icg.StatusChanged += itemCreated; return; } } }