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的最大深度和最大子节点数量,避免遍历浪费太多时间

最新文章

  1. 程序设计入门——C语言 第6周编程练习 1 分解质因数(5分)
  2. u3d_shader_surface_shader_5
  3. Swift 1.0: missing argument label &#39;xxx&#39; in call
  4. (BZOJ4538)HNOI2016 网络
  5. UI之UItableView重用机制的性能问题
  6. LINUX 内核月报 taobao
  7. 线程同步(AutoResetEvent与ManualResetEvent)
  8. for语句嵌套使用 实现9*9乘法表
  9. P - Atlantis - hdu1542(求面积)
  10. Oracle-nomount/mount/open
  11. bootstrap 智能表单 demo示例
  12. Scala的XML操作
  13. hdu 3549最大流Ford-Fulkerson算法
  14. Requests库作者另一神器Pipenv的用法
  15. java基础之IO流及递归理解
  16. Dynamics 365的审核日志分区删除超时报错怎么办?
  17. 河北大学python选修课00次作业
  18. 为爱好舞蹈的人们做的软件,细究数据结构,操作系统,磁盘原理,用java/c/c++写一个开源 MP3助手
  19. ABP框架系列之十二:(Audit-Logging-审计日志)
  20. 设置nginx和php-fpm更改上传文件大小限制

热门文章

  1. [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现
  2. Java实现对日期上旬中旬下旬格式化
  3. 【codeforces 505C】Mr.Kitayuta,the Treasure Hunter
  4. Django项目:CMDB(服务器硬件资产自动采集系统)--05--05CMDB采集硬件数据的插件
  5. [LOJ#162]模板题-快速幂2
  6. centos7下python3和pycharm安装
  7. 部分树形DP的优化
  8. mysqldump与mydumper
  9. 关于 webpack的总结
  10. LUOGU P3539 [POI2012]ROZ-Fibonacci Representation