原文: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. Ubuntu 16.04.4 LTS + Ambari 2.6.1.5 + HDP 2.6.4.0 安装部署

    服务器 主机名 master slave1 slave2 slave3 IP 192.168.1.40 192.168.1.41 192.168.1.42 192.168.1.43 离线包服务器: 1 ...

  2. CentOS7 下源码安装 python3

    CentOS 7 下源码安装 python3   在CentOS7下,默认安装的是python2.7:为满足项目要求,安装python3 的方法如下:   1. 首先安装python3.6可能使用的依 ...

  3. js,H5本地存储

    //存储本地存储----setItem(存储名称,数据名称) var c={name:"man",sex:"woman"}; localStorage.setI ...

  4. [iOS] KVC 和 KVO

    开发iOS经常会看见KVO和KVC这两个概念,特地了解了一下. 我的新博客wossoneri.com link KVC Key Value Coding KVC是一种用间接方式访问类的属性的机制.比如 ...

  5. javascript模块化编程-详解立即执行函数表达式IIFE

    一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式.  像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...

  6. 万能Makefile,前戏做足项目做起来才顺畅。

    # 获取要编译的源码 SRC :=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) # 编译参数 CC :=g++ STD :=-std=c++ ...

  7. 5.1Python函数(一)

    目录 目录 前言 (一)函数的基本知识 (二)函数的基本使用 ==1.函数的简单定义== ==2.传值函数== (3)输出效果 ==3.不定长函数== ==4.缺省函数== ==5.函数的传值过程== ...

  8. ccf-20171203 Crontab问题

    这题有如下几个点要注意: 1.最开始输出的开始时间和截止时间,这里是不包含截止时间的. 2.月份和星期的英文表示是大小写任意的,并未规定必须是Sat这种形式. 3.星期天的数字标识是0. 我的思路是, ...

  9. IntelliJ IDEA 项目结构旁边出现 0%classes,0% lines covered

    不知道一不小心点到哪里,项目变成如下形式 使用ctrl +  Alt + F6弹出如下框,取消勾选-->点击Show Selected就可以去掉了 官网解释

  10. Python3编写网络爬虫12-数据存储方式五-非关系型数据库存储

    非关系型数据库存储 NoSQL 全称 Not Only SQL 意为非SQL 泛指非关系型数据库.基于键值对 不需要经过SQL层解析 数据之间没有耦合性 性能非常高. 非关系型数据库可细分如下: 键值 ...