// ****************************************************************** 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; } } }
// ****************************************************************** /// <summary> /// Expand any ItemsControl (TreeView, TreeViewItem, ListBox, ComboBox, ...) and their childs if any (TreeView) /// </summary> /// <param name="ic"></param> /// <param name="actionItemExpanded"></param> /// <param name="referenceCounterTracker"></param> public static void ExpandSubContainers(ItemsControl ic, Action <TreeViewItem, object> actionItemExpanded, ReferenceCounterTracker referenceCounterTracker) { ItemContainerGenerator icg = ic.ItemContainerGenerator; { if (icg.Status == GeneratorStatus.ContainersGenerated) { ExpandSubWithContainersGenerated(ic, actionItemExpanded, referenceCounterTracker); } else if (icg.Status == GeneratorStatus.NotStarted) { ActionHolder actionHolder = new ActionHolder(); EventHandler itemCreated = delegate(object sender, EventArgs eventArgs) { var icgSender = sender as ItemContainerGenerator; if (icgSender.Status == GeneratorStatus.ContainersGenerated) { ExpandSubWithContainersGenerated(ic, actionItemExpanded, referenceCounterTracker); // Never use the following method in BeginInvoke due to ICG recycling. The same icg could be // used and will keep more than one subscribers which is far from being intended // ic.Dispatcher.BeginInvoke(actionHolder.Action, DispatcherPriority.Background); // Very important to unsubscribe as soon we've done due to ICG recycling. actionHolder.Execute(); referenceCounterTracker.ReleaseRef(); } }; referenceCounterTracker.AddRef(); actionHolder.Action = new Action(() => icg.StatusChanged -= itemCreated); icg.StatusChanged += itemCreated; // Next block is only intended to protect against any race condition (I don't know if it is possible ? How Microsoft implemented it) // I mean the status changed before I subscribe to StatusChanged but after I made the check about its state. if (icg.Status == GeneratorStatus.ContainersGenerated) { ExpandSubWithContainersGenerated(ic, actionItemExpanded, referenceCounterTracker); } } } }