原文: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. “一切都是消息”--iMSF(即时消息服务框架)之【发布-订阅】模式

    MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately)消息,所以iMSF就是 immediately Message S ...

  2. python第六十一天,第六十二天 redis

    redis 缓存系统 redis是业界主流的key-value nosql 数据库之一.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).se ...

  3. vs2012\2013\2015 添加 ActiveX制作控件插件 Visual Studio Installer

    由于vs2012.2013 之后的版本升级,之前用vs2010 开发制作的ActvieX控件在高版本12.13上不兼容,需要安装插件支持: 如果是vs2013版本,可参照以下方式下载后安装,若是其他版 ...

  4. 彻底卸载删除Win10易升,禁止再生

    易升是微软推出的win10升级工具.用户可通过易升一键升级win10. 因为我的电脑已经是win10的系统,所以我也不需要升级.也不想升级,因为我从网上了解到升级后的系统反而没有升级前的好用. 微软的 ...

  5. python基础、字符串和if条件语句,while循环,跳出循环、结束循环

    一:Python基础 1.文件后缀名: .py 2.Python2中读中文要在文件头写: -*-coding:utf8-*- 3.input用法      n为变量,代指某一变化的值 n = inpu ...

  6. zookeeper-03 命令行操作

    1. 前言 在3台机器分别部署了zookeeper-3.4.5,本文操作是在此基础上进行的.部署详情参见上一篇文章 2. 客户端登录与帮助查看 # 由于是集群模式,所以可以在3台机器的其中任意一台进行 ...

  7. 百度地图API开发

    1.首先申请百度地图秘钥 http://lbsyun.baidu.com/ 2.需要填一个申请的界面 3.申请后会有类似的东西 4.之后参照以下网址进行MFC编译 mfc webbrowser控件使用 ...

  8. VRS生成的虚拟观测值存在的问题

    目前生成的虚拟观测值. 天津的版本,如果有数据库中有天线类型,那么会对天线类型改正了两次. 解决方法:在生成虚拟观测值编码的部分,注释掉天线改正的部分. 对结果的影响:错误版本生成的虚拟观测值,移动站 ...

  9. pb中遍历查询数据库数据问题(数据库为 sql server)

    指针可以实现但是不推荐 例如:(部分代码) for ll_a = 1 to ll_count    ll_b = ll_i +  ll_a  //插入行行号先下移一位    dw_main.inser ...

  10. centos iftop iotop htop

    centos6.4安装iftopyum install gccyum -y install libpcap libpcap-develyum -y install ncurses ncurses-de ...