Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Although the accepted answer will work most of the time. It could happen to not work because the object is created on another thread not controlled at all by the dispatcher.</p> <p>Like mentionned earlier, the problem lie from the fact that the TreeViewItem is created in another thread from the dispatcher one.</p> <p>I personnally think that the proper solution is more complex. I know it is bad to hear but I really think it is so. My code should work when virtualized or not. Also, you could remove any reference not needed (I did not verify).</p> <p>My solution is based on a data model where every node inherits from the same root: MultiSimBase object, but it is not a requirement.</p> <p>Everything start from SetSelectedTreeViewItem() which activate (+set focus and bring into view) the newly added item.</p> <p>Hope it could help or inspired some... Happy coding !!!</p> <p>Code of the form:</p> <pre><code> // ****************************************************************** private List&lt;MultiSimBase&gt; SetPathListFromRootToNode(MultiSimBase multiSimBase, List&lt;MultiSimBase&gt; listTopToNode = null) { if (listTopToNode == null) { listTopToNode = new List&lt;MultiSimBase&gt;(); } listTopToNode.Insert(0, multiSimBase); if (multiSimBase.Parent != null) { SetPathListFromRootToNode(multiSimBase.Parent, listTopToNode); } return listTopToNode; } // ****************************************************************** private void SetSelectedTreeViewItem(MultiSimBase multiSimBase) { List&lt;MultiSimBase&gt; listOfMultiSimBasePathFromRootToNode = SetPathListFromRootToNode(multiSimBase); TreeViewStudy.SetItemHierarchyVisible(listOfMultiSimBasePathFromRootToNode, (tvi) =&gt; { tvi.IsSelected = true; tvi.Focus(); tvi.BringIntoView(); }); } </code></pre> <p>And now generic code:</p> <pre><code>using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Threading; namespace HQ.Util.Wpf.WpfUtil { public static class TreeViewExtensions { public delegate void OnTreeViewVisible(TreeViewItem tvi); private static void SetItemHierarchyVisible(ItemContainerGenerator icg, IList listOfRootToNodePath, OnTreeViewVisible onTreeViewVisible = null) { Debug.Assert(icg != null); if (icg != null) { if (listOfRootToNodePath.Count == 0) // nothing to do return; TreeViewItem tvi = icg.ContainerFromItem(listOfRootToNodePath[0]) as TreeViewItem; if (tvi != null) // Due to threading, always better to verify { listOfRootToNodePath.RemoveAt(0); if (listOfRootToNodePath.Count == 0) { if (onTreeViewVisible != null) onTreeViewVisible(tvi); } else { if (!tvi.IsExpanded) tvi.IsExpanded = true; SetItemHierarchyVisible(tvi.ItemContainerGenerator, listOfRootToNodePath, onTreeViewVisible); } } else { ActionHolder actionHolder = new ActionHolder(); EventHandler itemCreated = delegate(object sender, EventArgs eventArgs) { var icgSender = sender as ItemContainerGenerator; tvi = icgSender.ContainerFromItem(listOfRootToNodePath[0]) as TreeViewItem; if (tvi != null) // Due to threading, it is always better to verify { SetItemHierarchyVisible(icg, listOfRootToNodePath, onTreeViewVisible); actionHolder.Execute(); } }; actionHolder.Action = new Action(() =&gt; icg.StatusChanged -= itemCreated); icg.StatusChanged += itemCreated; return; } } } // ****************************************************************** /// &lt;summary&gt; /// 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. /// &lt;/summary&gt; /// &lt;param name="treeView"&gt;TreeView where an item has to be set visible&lt;/param&gt; /// &lt;param name="collectionOfRootToNodePath"&gt;Any of collection that implement ICollection like a generic List. /// The collection should have every objet of the path to the targeted item from the top to the target. /// For example for an apple tree: AppleTree (index 0), Branch4, SubBranch3, Leaf2 (index 3)&lt;/param&gt; /// &lt;param name="onTreeViewVisible"&gt;Optionnal&lt;/param&gt; public static void SetItemHierarchyVisible(this TreeView treeView, IList listOfRootToNodePath, OnTreeViewVisible onTreeViewVisible = null) { ItemContainerGenerator icg = treeView.ItemContainerGenerator; if (icg == null) return; // Is tree loaded and initialized ??? SetItemHierarchyVisible(icg, listOfRootToNodePath, onTreeViewVisible); } </code></pre> <p>And</p> <pre><code> using System; namespace HQ.Util.Wpf.WpfUtil { // Requested to unsubscribe into an anonymous method that is a delegate used for a one time execution // http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/df2773eb-0cc1-4f3a-a674-e32f2ef2c3f1/ public class ActionHolder { public void Execute() { if (Action != null) { Action(); } } public Action Action { get; set; } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload