using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Threading; using HQ.Util.General; namespace HQ.Util.Wpf.WpfUtil { public static class TreeViewExtensions { // ****************************************************************** public delegate void OnTreeViewVisible(TreeViewItem tvi); public delegate void OnItemExpanded(TreeViewItem tvi, object item); public delegate void OnAllItemExpanded(); // ****************************************************************** 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; } } } // ****************************************************************** /// /// 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. /// /// TreeView where an item has to be set visible /// 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) /// Optionnal public static void SetItemHierarchyVisible(this TreeView treeView, IEnumerable
和
using System; using System.Threading; namespace HQ.Util.General { public delegate void CountToZeroAction(); public class ReferenceCounterTracker { private Action _actionOnCountReachZero = null; private int _count = 0; public ReferenceCounterTracker(Action actionOnCountReachZero) { _actionOnCountReachZero = actionOnCountReachZero; } public void AddRef() { Interlocked.Increment(ref _count); } public void ReleaseRef() { int count = Interlocked.Decrement(ref _count); if (count == 0) { if (_actionOnCountReachZero != null) { _actionOnCountReachZero(); } } } } }