// ******************************************************************
        /// <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;
                }
            }
        }