VisualTreeHelper使用——使用BFS实现高效率的视觉对象搜索
2024-09-08 15:55:00
BFS,即广度优先搜索,是一种典型的图论算法。BFS算法与DFS(深度优先搜索)算法相对应,都是寻找图论中寻路的常用算法,两者的实现各有优点。
其中DFS算法常用递归实现,也就是常见的一条路找到黑再找另一条。如果我们要找的数据存储在一棵树最靠左侧的一边时,DFS的好处就显现出来了。无论数据在树的多深,DFS都能在线性的时间内找出这个数据。
而BFS算法常用队列实现,在查找树内对象时,会由树的根节点,一层一层向下找到目标。BFS的好处在于不管数据存在树的哪个节点,BFS都能以一个比较恒定的速度找到对象,这个速度几乎只与没寻找的深度和每层的节点数量相关。
所以在遍历视觉树时使用BFS相较于DFS有什么好处呢?
一个很明显的视觉树遍历特点就是,一般要找到的视觉对象都不会存储在离根节点特别远的地方。此时BFS相比DFS更不容易出现一条分支摸到黑啥都没找的情况。
话不多少了,上代码!
public static class VisualTreeExtension
{ /// <summary>
/// Find all children T in dpObj using BFS.
/// </summary>
/// <param name="maxDepth">max finding depth of visual tree.</param>
/// <param name="maxChildCount">maximum number of child nodes. Whose number of child nodes exceeds this value will be excluded</param>
/// <returns></returns>
public static IEnumerable<T> GetChild<T>(this DependencyObject dependencyObject, uint maxDepth = uint.MaxValue, uint maxChildCount = )
where T : DependencyObject
{
int depth = ;
int count = VisualTreeHelper.GetChildrenCount(dependencyObject);
Queue<DependencyObject> qObjs = new Queue<DependencyObject>();
for (int i = ; i < count; i++)
{
qObjs.Enqueue(VisualTreeHelper.GetChild(dependencyObject, i));
} while (qObjs.Count != )
{
if (depth > maxDepth)
yield break;
depth++;
count = qObjs.Count;
for (int i = ; i < count; i++)
{
var obj = qObjs.Dequeue();
if (obj is T result)
yield return result;
int child_count = VisualTreeHelper.GetChildrenCount(obj);
if (child_count > maxChildCount)
continue;
for (int j = ; j < child_count; j++)
{
qObjs.Enqueue(VisualTreeHelper.GetChild(obj, j));
}
}
}
} /// <summary>
/// Find all children T in dpObj using BFS.
/// </summary>
/// <param name="maxDepth">max finding depth of visual tree.</param>
/// <param name="maxChildCount">maximum number of child nodes. Whose number of child nodes exceeds this value will be excluded</param>
/// <returns></returns>
public static IEnumerable<T> GetChild<T>(this DependencyObject dependencyObject, string name, uint maxDepth = uint.MaxValue, uint maxChildCount = )
where T : FrameworkElement
{
int depth = ;
int count = VisualTreeHelper.GetChildrenCount(dependencyObject);
Queue<DependencyObject> qObjs = new Queue<DependencyObject>(count);
for (int i = ; i < count; i++)
{
qObjs.Enqueue(VisualTreeHelper.GetChild(dependencyObject, i));
} while (qObjs.Count != )
{
if (depth > maxDepth)
yield break;
depth++;
count = qObjs.Count;
for (int i = ; i < count; i++)
{
var obj = qObjs.Dequeue();
if (obj is T result && result.Name == name)
yield return result;
int child_count = VisualTreeHelper.GetChildrenCount(obj);
if (child_count > maxChildCount)
continue;
for (int j = ; j < child_count; j++)
{
qObjs.Enqueue(VisualTreeHelper.GetChild(obj, j));
}
}
}
}
}
使用方法:
var scrollViewer = listView.GetChild<ScrollViewer>().First();
也可以手动指定BFS的最大深度和最大子节点数量,避免遍历浪费太多时间
最新文章
- 程序设计入门——C语言 第6周编程练习 1 分解质因数(5分)
- u3d_shader_surface_shader_5
- Swift 1.0: missing argument label &#39;xxx&#39; in call
- (BZOJ4538)HNOI2016 网络
- UI之UItableView重用机制的性能问题
- LINUX 内核月报 taobao
- 线程同步(AutoResetEvent与ManualResetEvent)
- for语句嵌套使用 实现9*9乘法表
- P - Atlantis - hdu1542(求面积)
- Oracle-nomount/mount/open
- bootstrap 智能表单 demo示例
- Scala的XML操作
- hdu 3549最大流Ford-Fulkerson算法
- Requests库作者另一神器Pipenv的用法
- java基础之IO流及递归理解
- Dynamics 365的审核日志分区删除超时报错怎么办?
- 河北大学python选修课00次作业
- 为爱好舞蹈的人们做的软件,细究数据结构,操作系统,磁盘原理,用java/c/c++写一个开源 MP3助手
- ABP框架系列之十二:(Audit-Logging-审计日志)
- 设置nginx和php-fpm更改上传文件大小限制
热门文章
- [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现
- Java实现对日期上旬中旬下旬格式化
- 【codeforces 505C】Mr.Kitayuta,the Treasure Hunter
- Django项目:CMDB(服务器硬件资产自动采集系统)--05--05CMDB采集硬件数据的插件
- [LOJ#162]模板题-快速幂2
- centos7下python3和pycharm安装
- 部分树形DP的优化
- mysqldump与mydumper
- 关于 webpack的总结
- LUOGU P3539 [POI2012]ROZ-Fibonacci Representation