public static void SelectOne(this TreeView treeView, object item, bool isValue) { ApplyActionToAllTreeViewItems(treeView, itemsControl => { object equalItem = itemsControl.Header; if (isValue) { equalItem = BindingHelper.Eval <object>(equalItem, treeView.SelectedValuePath); } if (equalItem.Equals(item)) { itemsControl.IsSelected = true; itemsControl.BringIntoView(); itemsControl.Focus(); return; } else { itemsControl.IsSelected = false; } bool wasExpanded = itemsControl.IsExpanded; itemsControl.IsExpanded = true; a7UIHelper.WaitForPriority(DispatcherPriority.ContextIdle); itemsControl.IsExpanded = wasExpanded; }); }
/// <summary> /// Finds the provided object in an ItemsControl's children and selects it /// </summary> /// <param name="parentContainer">The parent container whose children will be searched for the selected item</param> /// <param name="itemToSelect">The item to select</param> /// <returns>True if the item is found and selected, false otherwise</returns> private static bool ExpandAndSelectItem(ItemsControl parentContainer, object itemToSelect, bool isValue, string valuePath, Action <TreeViewItem> beforeSelection, Action <TreeViewItem> afterSelection) { //check all items at the current level foreach (object item in parentContainer.Items) { TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; object equalItem = item; if (isValue) { equalItem = BindingHelper.Eval <object>(item, valuePath); } //if the data item matches the item we want to select, set the corresponding //TreeViewItem IsSelected to true if (currentContainer != null) { if (equalItem.Equals(itemToSelect)) { if (beforeSelection != null) { beforeSelection(currentContainer); } currentContainer.IsSelected = true; currentContainer.BringIntoView(); currentContainer.Focus(); if (afterSelection != null) { afterSelection(currentContainer); } //the item was found return(true); } else if (currentContainer.IsSelected) { currentContainer.IsSelected = false; } } } //if we get to this point, the selected item was not found at the current level, so we must check the children foreach (object item in parentContainer.Items) { TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem; //if children exist if (currentContainer != null && currentContainer.Items.Count > 0) { //keep track of if the TreeViewItem was expanded or not bool wasExpanded = currentContainer.IsExpanded; //expand the current TreeViewItem so we can check its child TreeViewItems currentContainer.IsExpanded = true; //if the TreeViewItem child containers have not been generated, we must listen to //the StatusChanged event until they are if (currentContainer.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) { //store the event handler in a variable so we can remove it (in the handler itself) EventHandler eh = null; eh = new EventHandler(delegate { if (currentContainer.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated) { if (ExpandAndSelectItem(currentContainer, itemToSelect, isValue, valuePath, beforeSelection, afterSelection) == false) { //The assumption is that code executing in this EventHandler is the result of the parent not //being expanded since the containers were not generated. //since the itemToSelect was not found in the children, collapse the parent since it was previously collapsed currentContainer.IsExpanded = false; } //remove the StatusChanged event handler since we just handled it (we only needed it once) currentContainer.ItemContainerGenerator.StatusChanged -= eh; } }); currentContainer.ItemContainerGenerator.StatusChanged += eh; } else //otherwise the containers have been generated, so look for item to select in the children { if (ExpandAndSelectItem(currentContainer, itemToSelect, isValue, valuePath, beforeSelection, afterSelection) == false) { //restore the current TreeViewItem's expanded state currentContainer.IsExpanded = wasExpanded; } else //otherwise the node was found and selected, so return true { return(true); } } } } //no item was found return(false); }