本文将告诉大家如何在 UNO 里面将界面的层级结构输出到调试窗口

实现方法非常简单,和 WPF 或 UWP 等的方法是一样的,那就是通过可视化树遍历的方式,如以下代码

    static class UISpyHelper
{
public static void Spy(this DependencyObject element)
{
Uno.Extensions.IndentedStringBuilder builder = new ();
SpyInner(element, builder);
var spyText = builder.ToString();
Debug.WriteLine(spyText);
} private static void SpyInner(DependencyObject element, Uno.Extensions.IndentedStringBuilder builder)
{
var name = string.Empty;
if (element is FrameworkElement frameworkElement)
{
name = frameworkElement.Name;
}
builder.AppendLine($"{name}({element.GetType().FullName})\r\n"); for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
using var t = builder.Indent();
var child = VisualTreeHelper.GetChild(element, i);
SpyInner(child, builder);
}
}
}

通过以上的代码即可将传入的 UI 上的控件进行遍历输出层次结构。比如传入一个 TextBox 控件,可以看到大概如下的输出内容

TextBox(Microsoft.UI.Xaml.Controls.TextBox)
RootBorder(Microsoft.UI.Xaml.Controls.Border)
Root(Microsoft.UI.Xaml.Controls.Grid)
(Microsoft.UI.Xaml.Controls.Border)
IconPresenter(Microsoft.UI.Xaml.Controls.ContentPresenter)
ContentElement(Microsoft.UI.Xaml.Controls.ScrollViewer)
(Microsoft.UI.Xaml.Controls.Border)
Root(Microsoft.UI.Xaml.Controls.Grid)
ScrollContentPresenter(Microsoft.UI.Xaml.Controls.ScrollContentPresenter)
(Microsoft.UI.Xaml.Controls.TextBlock)
VerticalScrollBar(Microsoft.UI.Xaml.ElementStub)
HorizontalScrollBar(Microsoft.UI.Xaml.ElementStub)
ScrollBarSeparator(Microsoft.UI.Xaml.Controls.Border)
(Microsoft.UI.Xaml.Controls.Border)
PlaceholderElement(Microsoft.UI.Xaml.Controls.TextBlock)
DeleteButton(Microsoft.UI.Xaml.Controls.Button)
ButtonLayoutGrid(Microsoft.UI.Xaml.Controls.Grid)
GlyphElement(Microsoft.UI.Xaml.Shapes.Path)

在 UNO 里面也有自带的方法,通过 TreeGraph 打印出来,代码如下

using Uno.UI.Extensions;

        var treeGraph = this.TreeGraph();

以上的 treeGraph 在我的简单的应用的输出内容大概如下

ConnectionUserControl // Actual=624x379, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Grid // Actual=624x379, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Grid // Actual=624x48, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Image // Actual=24x24, HV=Left/Stretch, Margin=[18,0,0,0], Opacity=1, Visibility=Visible
TextBlock // Actual=146x20.3203125, HV=Stretch/Center, Margin=[50,0,0,0], Padding=0, Opacity=1, Visibility=Visible
Button#AboutButton // Actual=24x24, HV=Right/Center, CornerRadius=0, Margin=[0,0,149,0], Padding=[8,4], Opacity=1, Visibility=Visible
Grid // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Path // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible
Button // Actual=24x24, HV=Right/Center, CornerRadius=0, Margin=[0,0,109,0], Padding=[8,4], Opacity=1, Visibility=Visible
Grid // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Path // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible
Border // Actual=1x14, HV=Right/Stretch, CornerRadius=0, Margin=[0,0,93,0], Padding=0, Opacity=1, Visibility=Visible
Button // Actual=24x24, HV=Right/Center, CornerRadius=0, Margin=[0,0,58,0], Padding=[8,4], Opacity=1, Visibility=Visible
Grid // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Path // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible
Button // Actual=24x24, HV=Right/Center, CornerRadius=0, Margin=[0,-2,18,0], Padding=[8,4], Opacity=1, Visibility=Visible
Grid // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Path // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible
Grid#ContentGrid // Actual=640x371, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Border // Actual=360x292, HV=Stretch/Top, CornerRadius=[4,4,0,0], Margin=0, Padding=0, Opacity=1, Visibility=Visible
Grid // Actual=360x292, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
TextBlock // Actual=193.546875x54.48046875, HV=Center/Stretch, Margin=[0,24,0,0], Padding=0, Opacity=1, Visibility=Visible
Grid // Actual=160x160, HV=Stretch/Top, CornerRadius=0, Margin=[0,68,0,0], Padding=0, Opacity=1, Visibility=Visible
Image // Actual=0x0, HV=Stretch/Stretch, Margin=4, Opacity=1, Visibility=Collapsed
Grid // Actual=0x0, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Collapsed
Path#ErrorPath // Actual=0x0, HV=Center/Center, Margin=0, Opacity=1, Visibility=Collapsed
CircleLoading#CircleLoading // Actual=32x32, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Viewbox // Actual=32x32, HV=Center/Center, Margin=0, Opacity=1, Visibility=Visible
Border // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Grid#RootGrid // Actual=24x24, HV=Stretch/Stretch, CornerRadius=0, Margin=0, Padding=0, Opacity=1, Visibility=Visible
Path#Part1 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.16, Visibility=Visible
Path#Part2 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.28, Visibility=Visible
Path#Part3 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.4, Visibility=Visible
Path#Part4 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.52, Visibility=Visible
Path#Part5 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.64, Visibility=Visible
Path#Part6 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.76, Visibility=Visible
Path#Part7 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=0.88, Visibility=Visible
Path#Part8 // Actual=24x24, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible
Image#QrCodeImage // Actual=160x160, HV=Stretch/Stretch, Margin=0, Opacity=1, Visibility=Visible

官方的 TreeGraph 方法和前文的使用 VisualTreeHelper 获取到的元素对象都是相同的,原因是 TreeGraph 方法底层实现如下

using _View = Windows.UI.Xaml.DependencyObject;

  internal static IEnumerable<_View> EnumerateChildren(this _View? reference)
{
return Enumerable
.Range(0, VisualTreeHelper.GetChildrenCount(reference))
.Select(x => VisualTreeHelper.GetChild(reference, x));
}

更多请看 Inspecting the runtime visual tree of an Uno app

dotnet UNO 如何在调试下输出界面层级结构的更多相关文章

  1. 痞子衡嵌入式:浅析IAR下调试信息输出机制之硬件UART外设

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之硬件UART外设. 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我们可以比较容易地 ...

  2. 痞子衡嵌入式:浅析IAR下调试信息输出机制之半主机(Semihosting)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之半主机(Semihosting). 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我 ...

  3. 利用 Serial Over Lan(SOL)搭建 XEN 的调试信息输出环境

    如有转载,请注明出处与本文连接,谢谢! 修改XEN的源码实现额外的功能,需要有一个调试环境来得到XEN的调试信息(有关源码编译并安装 XEN 请阅读我以前的博文:在CentOS下源码安装 Xen并搭建 ...

  4. Anjuta 调试无输出 warning: GDB: Failed to set controlling terminal

    调试无输出,起初以为是那个warning的问题,后来才知道这个系统printf直到遇到'\n'换行符才输出,VC6用习惯了没想到还有这样的,网上说这样是节省系统资源. 那个warning暂时还没看到影 ...

  5. 关于VS中的调试信息输出

    有时候一些项目的调试信息不方便输出到界面中,比如ASP.NET或者WPF之类的 可以使用Debug.WriteLine()等方法输出到"输出"窗口,不过"输出" ...

  6. 第七课 GDB调试 (下)

    1序言: 通过前面一节第六课 GDB调试 (下)文章,可以掌握理解了gdb调试:怎么启动.运行,打断点.查看变量.甚至改变变量等的知识,今天来大概讲解下调试bug的类型. 2知识点: 2.1 就像之前 ...

  7. 使用 DML 自定义调试器输出

    调试器标记语言 (DML) 提供了一种机制增强来自调试器和扩展的输出. 与 HTML 类似,调试器的标记支持允许将输出包括显示指令和额外非显示的标记窗体中的信息. 调试器用户界面,WinDbg 等中分 ...

  8. 点击TableView中某行进入下一级界面(Swift)

    TableView这个控件在iOS的开发中非常的常见,他可以较好的展示一个层级结构.这里主要介绍,在点击某个条目的时候,如何进行跳转的下一个界面.以下是官方的关于这个跳转如何去实现,和如何去传递数据的 ...

  9. PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么?

    PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么? 代码如下: <?php $arr = array('one','two','three'); fo ...

  10. windows下VC界面 DIY系列1----写给想要写界面的C++程序猿的话

    非常早就想写关于C++ UI开发的一系列博文,博客专栏刚审核通过,就立即開始刷博文,不能辜负自己的一番热血,我并非写界面的高手,仅仅想通过写博文提高我自己的技术积累,也顺便帮助大家解决界面开发的瓶颈. ...

随机推荐

  1. HTML/ CSS 入门

    前言 我们在之前的学习中,对于网络有了一定的了解.现在我们来学习一些基础的 HTML/ CSS 知识.希望阅读完这篇文章能达到编写简单页面的程度. 目录: HTML/ CSS 的发明: HTML 基础 ...

  2. ssm整合简单配置

    最近由于系统重装,之前已经写好了的框架都被我删的一干二净,于是自己动手重新搭了个简单的ssm(spring springmvc mybatis) 运行环境 (java1.8,Tomcat8.5,mav ...

  3. Unit 1 Computer hardware【石家庄铁道大学-专业英语课程复习资料】

    Unit 1 Computer hardware 1.Introduction of computer A computer is a machine that can be instructed t ...

  4. Go~开发笔记~目录

    Go(又称为Golang)是一门由Google开发的开源编程语言,于2009年首次公开发布.Go语言被设计用来提高软件开发的效率和可靠性,在处理大规模系统时表现出色.以下是Go语言的一些特点和优势: ...

  5. 17 JavaScript 中的call和apply

    17 JavaScript 中的call和apply 对于咱们逆向工程师而言. 并不需要深入的理解call和apply的本质作用. 只需要知道这玩意执行起来的逻辑顺序是什么即可 在运行时. 正常的js ...

  6. #Kruskal重构树,Dijkstra,倍增#洛谷 4768 [NOI2018]归程

    题目传送门 分析 首先Dijkstra是必需的(关于SPFA,它死了233) 无向图,所以先求出1号节点到所有点的距离,然后肯定希望起点能驾驶到离一号点最短的汽车可到的地方 但是怎么办,考虑海拔大的边 ...

  7. #李超线段树,树链剖分#洛谷 4069 [SDOI2016]游戏

    题目 分析 就是把线段扔到了树上,注意区间查询要比较两个端点的函数值, 把区间赋值转换成两部分,从起点到LCA的区间是斜率为负数的线段, 从终点到LCA的区间是斜率为正数的线段. 代码 #includ ...

  8. SQL PRIMARY KEY 约束- 唯一标识表中记录的关键约束

    SQL NOT NULL 约束 SQL NOT NULL 约束用于强制确保列不接受 NULL 值.这意味着该字段始终包含一个值,而不允许插入新记录或更新记录时不提供此字段的值. 在 CREATE TA ...

  9. Sqlite数据库联合查询及表复制等详述

    外键:一般在两个表之间要建立关联时候,创建一个列创建 为外键(UserInfos-DeptId),它在另一个表必须是主键(DeptInfos-DeptId) 元素约束:主键约束:主要区别内容相同的行, ...

  10. java excel关联导入数据格式为一对多

    java excel关联导入数据格式为一对多 java 表格读取时一行一行的读取 将每行数据放入list  根据 list.stream().filter(m->m.getCode().equa ...