WPF中TreeView.BringIntoView方法的替代方案

WPF中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;
    }
  }

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索treeview
, item
, generated
, expand
, children
, The
expander
wpf treeview、wpf treeview 样式、wpf treeview 绑定、wpf treeview数据绑定、wpf treeview 图标,以便于您获取更多的相关知识。

时间: 2025-01-26 13:50:47

WPF中TreeView.BringIntoView方法的替代方案的相关文章

WPF中TreeView控件在选中节点后如何获取其父节点,再父节点信息

问题描述 winform中TreeView控件中,在选中某个节点后,可以用e.Node.Parent来获取其父节点信息,再父节点可以用e.Node.Parent.Parent,而在WPF中此方法似乎不行,如,在选中某个节点后TreeViewItemitem=(TreeViewItem)treeCourseInfo.SelectedItem;可以获取该节点的信息if(item.Header.ToString()=="科目信息",但是不知该如何获取其父节点,再父节点.....信息,各位有谁

关于WPF中treeView不能触发treeViewItem的MouseLeftButtonDown事件

问题描述 求助啊..........只有改成MouseLeftButtonUp才能触发.......可是又不满足要求效果不好treeView貌似屏蔽了路由MouseLeftButtonDown事件子节点treeViewItem无法触发MouseLeftButtonDown事件!改成隧道事件PreviewMouseLeftButtonDown倒是可以但是还是不满足要求.....或者用AddHandler(,,true)强制开启..不过却又另e.handel=true无效简单的说就是如何触发Tree

C#中TreeView组件使用方法初步

TreeView组件是由多个类来定义的,TreeView组件是由命名空间"System.Windows.Forms"中的"TreeView"类来定义的,而其中的节点(即Node),是由命名空间"System.Windows.Forms"中的"TreeNode"来定义的.所以当在程序中创建一个TreeView对象,其实只是创建了一个可以放置节点的"容器".而在这个容器中加入一个节点,其实就是加入了从"

C#中TreeView组件使用方法初步

TreeView组件是由多个类来定义的,TreeView组件是由命名空间"System.Windows.Forms"中的"TreeView"类来定义的,而其中的节点(即Node),是由命名空间"System.Windows.Forms"中的"TreeNode"来定义的.所以当在程序中创建一个TreeView对象,其实只是创建了一个可以放置节点的"容器".而在这个容器中加入一个节点,其实就是加入了从"

WPF中的ListBox实现按块显示元素的方法_C#教程

本文实例讲述了WPF中的ListBox实现按块显示元素的方法.分享给大家供大家参考,具体如下: 注意:需要设置ListBox的属性 ScrollViewer.HorizontalScrollBarVisibility="Disabled" 关键代码,WPF中有内置的WrapPanel控件,在ListBox.ItemsPanel中使用可以让元素按块显示 <ListBox.ItemsPanel> <ItemsPanelTemplate> <WrapPanel/

WPF中引入WindowsForms控件的方法_C#教程

本文实例讲述了WPF中引入WindowsForms控件的方法.分享给大家供大家参考,具体如下: 环境: [1]WindowsXP with SP3 [2]VS2008 with SP1 正文: Step1:在现有工程中引入Windows Forms 鼠标右键[References]->选择[Add Reference]->[.NET]标签页 加入[WindowsFormsIntegration]和[System.Windows.Forms]两项 Step2:在XAML文件里加入 [S2-1]加

WPF中使用文件浏览对话框的几种方式

原文:WPF中使用文件浏览对话框的几种方式 WPF本身并没有为我们提供文件浏览的控件, 也不能直接使用Forms中的控件,而文件浏览对话框又是我们最常用的控件之一. 下面是我实现的方式 方式1: 使用win32控件OpenFileDialog ? 1 2 3 4 5 6 7 Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog(); ofd.DefaultExt = ".xml"; ofd.Fil

UI前沿技术-WPF中的多点触控操作事件

就在过去几年,多点触控还只是科幻电影中表现未来主义的一种重要手法,现在俨然已经成为主流的用户界面技术.多点触控显示屏现在成了新型智能手机和 Tablet 计算机的标准显示屏.此外,它还可能在公共场所的计算机上普及,例如 Microsoft Surface 率先开发的网亭或桌面计算机. 实际存在的唯一不确定因素是多点触控在常规台式计算机上的普及.这种普及的最大障碍或许是长时间在垂直屏幕上移动手指所产生的疲劳(称为"大猩猩手臂").我个人希望多点触控的强大功能将切实推进桌面显示屏的重新设计

WPF中如何使用行为示例:Canvas控件拖放行为的演示

1.获取行为的支持,安装Expression Blend 4 SDK(http://www.microsoft.com/zh-cn/download/details.aspx?id=10801) . 2.创建行为库 (1)创建一个Class Project,添加WPF必备的以及WPF中支持行为必备的dll文件. 其中,System.Windows.Interactivity.dll组件在目录(需要安装Blend SDKs):C:\Program Files (x86)\Microsoft SDK