原文:WPF中TreeView.BringIntoView方法的替代方案

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;

}

}

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

  1. WPF中TreeView控件SelectedItemChanged方法的MVVM绑定

    问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...

  2. WPF中TreeView的使用

    因为项目中需要用到TreeView控件,由于是第一次在WPF中用到,因此事先在网上搜了很多关于数据绑定的方法介绍,个人经过实际应用,觉得WPF中的HierarchicalDataTemplate定义模 ...

  3. WPF中TreeView单击展开其子元素以及点击一个元素展开其他元素收起

    TreeView单击展开其子元素: 在WPF的TreeView控件中,要想展开它的子元素,我们必须要鼠标左键点两下或者右键点一下,那么我们怎样实现左键点一下就使它展开呢? Xaml: <Grid ...

  4. WPF中TreeView控件数据绑定和后台动态添加数据(二)

    写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...

  5. WPF中TreeView控件数据绑定和后台动态添加数据(一)

    数据绑定: 更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码. xaml代码: <TreeView Name="syntaxTree" ItemsSourc ...

  6. WPF中TreeView控件的使用案例

    WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...

  7. WPF中TreeView的+-号和连线style的一种实现

    最近又开始跟WPF打交道,项目里面用到了TreeView这个控件.然后需要有一个连线的外观就像是这样 二话不说,百度了一下,找到一个实现, 通道. 把代码拷贝到项目里面,跑了一下,看上去还不错.但是这 ...

  8. 在WPF中使用变通方法实现枚举类型的XAML绑定

    问题缘起 WPF的分层结构为编程带来了极大便利,XAML绑定是其最主要的特征.在使用绑定的过程中,大家都普遍的发现枚举成员的绑定是个问题.一般来说,枚举绑定多出现于与ComboBox配合的情况,此时我 ...

  9. WPF中三种方法得到当前屏幕的宽和高

    WPF程序中的单位是与设备无关的单位,每个单位是1/96英寸,如果电脑的DPI设置为96(每个英寸96个像素),那么此时每个WPF单位对应一个像素,不过如果电脑的DPI设备为120(每个英寸120个像 ...

随机推荐

  1. 聊聊HTTP gzip压缩与常见的Android网络框架

    版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/5835990.html 进入主题之前,我们先来看一下客户端与服 ...

  2. 【Java入门提高篇】Day34 Java容器类详解(十五)WeakHashMap详解

    源码详解系列均基于JDK8进行解析 说明 在Java容器详解系列文章的最后,介绍一个相对特殊的成员:WeakHashMap,从名字可以看出它是一个 Map.它的使用上跟HashMap并没有什么区别,所 ...

  3. python爬虫之pyquery学习

    相关内容: pyquery的介绍 pyquery的使用 安装模块 导入模块 解析对象初始化 css选择器 在选定元素之后的元素再选取 元素的文本.属性等内容的获取 pyquery执行DOM操作.css ...

  4. 浅谈C#依赖注入

    什么是依赖注入?不管是js中的一些前端框架还是,java,C#,php等中的一些后端开发框架中,都会涉及这个看着逼格略高的词语:依赖注入,越是看着好像很厉害的东西越是会让许多人学习产生恐惧,好像很厉害 ...

  5. 找Maven --> pom.xml --> groupId和artifactId的网站

    http://mvnrepository.com/ 在此记录

  6. 洛谷P2057 【SHOI2007】善意的投票

    洛谷P2057 [SHOI2007]善意的投票 题目链接 这道题是最小割的一个经典应用:划分集合. 题目的意思就是就是将所有的小朋友分为两个集合:同意睡觉和不同意睡觉的.不同的集合之间的边都要断开. ...

  7. LCA树链剖分

    LCA(Lowest Common Ancestor 最近公共祖先)定义如下:在一棵树中两个节点的LCA为这两个节点所有的公共祖先中深度最大的节点. 比如这棵树 结点5和6的LCA是2,12和7的LC ...

  8. 转://批量更新sequence的存储

    前言: ORACLE的序列(SEQUENCE)A SCHEMA OBJECT THAT GENERATES A SERIAL LIST OF UNIQUE NUMBERS FOR TABLE COLU ...

  9. Java中关于AbstractQueuedSynchronizer的入门(一)

    备注:博文仅仅是学习过程中的零散记录,后期整理. AbstractQueuedSynchronizer的简单介绍可以网上搜索,简单了解字段作用. 示例代码,分析获取锁的过程: import java. ...

  10. Python高级网络编程系列之第二篇

    在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好.我们写的这些简单的服务 ...