WPF中TreeView.BringIntoView方法的替代方案
原文: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方法的替代方案的更多相关文章
- WPF中TreeView控件SelectedItemChanged方法的MVVM绑定
问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...
- WPF中TreeView的使用
因为项目中需要用到TreeView控件,由于是第一次在WPF中用到,因此事先在网上搜了很多关于数据绑定的方法介绍,个人经过实际应用,觉得WPF中的HierarchicalDataTemplate定义模 ...
- WPF中TreeView单击展开其子元素以及点击一个元素展开其他元素收起
TreeView单击展开其子元素: 在WPF的TreeView控件中,要想展开它的子元素,我们必须要鼠标左键点两下或者右键点一下,那么我们怎样实现左键点一下就使它展开呢? Xaml: <Grid ...
- WPF中TreeView控件数据绑定和后台动态添加数据(二)
写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...
- WPF中TreeView控件数据绑定和后台动态添加数据(一)
数据绑定: 更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码. xaml代码: <TreeView Name="syntaxTree" ItemsSourc ...
- WPF中TreeView控件的使用案例
WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...
- WPF中TreeView的+-号和连线style的一种实现
最近又开始跟WPF打交道,项目里面用到了TreeView这个控件.然后需要有一个连线的外观就像是这样 二话不说,百度了一下,找到一个实现, 通道. 把代码拷贝到项目里面,跑了一下,看上去还不错.但是这 ...
- 在WPF中使用变通方法实现枚举类型的XAML绑定
问题缘起 WPF的分层结构为编程带来了极大便利,XAML绑定是其最主要的特征.在使用绑定的过程中,大家都普遍的发现枚举成员的绑定是个问题.一般来说,枚举绑定多出现于与ComboBox配合的情况,此时我 ...
- WPF中三种方法得到当前屏幕的宽和高
WPF程序中的单位是与设备无关的单位,每个单位是1/96英寸,如果电脑的DPI设置为96(每个英寸96个像素),那么此时每个WPF单位对应一个像素,不过如果电脑的DPI设备为120(每个英寸120个像 ...
随机推荐
- 你的BI应用处于什么阶段?解读Gartner BI成熟度模型
文 | 帆软数据应用研究院 水手哥 本文出自:知乎专栏<帆软数据应用研究院>——数据干货&资讯集中地 无论国内还是国外,多数企业的BI和分析平台建设之路并不平坦:一是对自身的环 ...
- Android View体系(三)属性动画
上一篇文章讲了View滑动的六种方法,其中一种是使用动画,这篇文章我们来讲一讲动画的其中一种:属性动画. 1.android视图动画和属性动画 视图动画我们都了解,它提供了AlphaAnimation ...
- Android architecture
- 利用trie树实现前缀输入提示及trie的python实现
代码来自https://github.com/wklken/suggestion/blob/master/easymap/suggest.py 还实现了缓存功能,搜索某个前缀超过一定次数时,进行缓存, ...
- 使用VSTS的Git进行版本控制(六)——拉取请求
使用VSTS的Git进行版本控制(六)--拉取请求 在将代码合并到主干之前,拉取请求让团队对特性分支的更改提供反馈.审阅人可以通过建议修改留下评论,并投票批准或拒绝代码. 任务1:在Visual St ...
- [20170916]sqlplus set array最小2补充.txt
[20170916]sqlplus set array最小2补充.txt --//以前写的贴子,链接http://blog.itpub.net/267265/viewspace-1453652/--/ ...
- [20170914]tnsnames.ora的管理.txt
[20170914]tnsnames.ora的管理.txt --//昨天朋友讲tnsnams.ora的内容太长了,而且许多不需要的.管理不方便.我记得以前写[20150409]tnsnames.ora ...
- sqlserver 拆分
有表tb, 如下:id value----------- -----------1 aa,bb2 aaa,bbb,ccc欲按id,分拆value列, 分拆后结果如下:id value--------- ...
- Android中使用databinding编译时出现的error:Execution failed for task ':app:dataBindingProcessLayoutsDebug'
Windows环境下使用svn对AndroidStudio更新代码时,总会在源文件中出现一堆乱码,尤其是xml文件中的乱码,不仅找起来费劲,改起来更费劲. 最近从svn更新代码之后,编译时出现了下面这 ...
- myeclipce项目导入eclipse中报错
1 找到新建页面所在的工程名字,然后左键选中,右键弹出功能菜单,选择Build Path,进入配置路径. 2 在java build path 页面的下选择Libraries栏目(默认选择),点击右侧 ...