Welcome

首页 / 软件开发 / .NET编程技术 / WPF中TreeView.BringIntoView方法的替代方案

WPF中TreeView.BringIntoView方法的替代方案2011-12-21WPF中TreeView.BringIntoView()方法并不是那么地好用,不少时候会没有效果,这里有一个替代方案,调用SelectItem()方法可以展开并呈现TreeView上指定的Item:

 public static class TreeViewHelper  {    /// <summary>    /// Expands all children of a TreeView    /// </summary>    /// <param name="treeView">The TreeView whose children will be expanded</param>    public static void ExpandAll(this TreeView treeView)    {      ExpandSubContainers(treeView);    }      /// <summary>    /// Expands all children of a TreeView or TreeViewItem    /// </summary>    /// <param name="parentContainer">The TreeView or TreeViewItem containing the children to expand</param>    private static void ExpandSubContainers(ItemsControl parentContainer)    {      foreach (Object item in parentContainer.Items)      {        TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;        if (currentContainer != null && currentContainer.Items.Count > 0)        {          //expand the item          currentContainer.IsExpanded = true;            //if the item"s children are not generated, they must be expanded          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              {                //once the children have been generated, expand those children"s children then remove the event handler                if (currentContainer.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)                {                  ExpandSubContainers(currentContainer);                  currentContainer.ItemContainerGenerator.StatusChanged -= eh;                }              });              currentContainer.ItemContainerGenerator.StatusChanged += eh;          }          else //otherwise the children have already been generated, so we can now expand those children          {            ExpandSubContainers(currentContainer);          }        }      }    }      /// <summary>    /// Searches a TreeView for the provided object and selects it if found    /// </summary>    /// <param name="treeView">The TreeView containing the item</param>    /// <param name="item">The item to search and select</param>    public static void SelectItem(this TreeView treeView, object item)    {      ExpandAndSelectItem(treeView, item);    }      /// <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)    {      //check all items at the current level      foreach (Object item in parentContainer.Items)      {        TreeViewItem currentContainer = parentContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;          //if the data item matches the item we want to select, set the corresponding        //TreeViewItem IsSelected to true        if (item == itemToSelect && currentContainer != null)        {          currentContainer.IsSelected = true;          currentContainer.BringIntoView();          currentContainer.Focus();            //the item was found          return true;        }      }        //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) == 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) == 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;    }  }