本文将告诉大家如何在 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. PyQt5 GUI编程

    一.PyQt5简介 PyQt5是一个用于创建图形用户界面(GUI)应用程序的跨平台工具集,它将Qt库(广泛用于C++编程语言中创建丰富的GUI应用程序)的功能包装给Python使用者.PyQt5是由R ...

  2. Vue中组件和插件有什么区别?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.组件是什么 回顾以前对组件的定义: 组件就是把图形.非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,在Vue中每一个. ...

  3. 记录--手把手带你开发一个uni-app日历插件(并发布)

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 相信我们在开发各类小程序或者H5,甚至APP时,会把uni-app作为一个技术选型,其优点在于一键打包多端运行,较为强大的跨平台的性能.但 ...

  4. 微信小程序中rich-text文本溢出(三个...)

    小程序中当rich-text中数据较多时就会出现溢出的现象 如下 此时的页面效果并不是很理想 我们可以在数据中给个div <div style="overflow: hidden;wh ...

  5. 使用Go语言开发一个短链接服务:一、基本原理

    章节  使用Go语言开发一个短链接服务:一.基本原理  使用Go语言开发一个短链接服务:二.架构设计  使用Go语言开发一个短链接服务:三.项目目录结构设计  使用Go语言开发一个短链接服务:四.生成 ...

  6. 做easyexcel遇到的问题数据库采用的mybatis-plus

    导入坐标 <!-- easyexcel依赖--><dependency> <groupId>com.alibaba</groupId> <arti ...

  7. KingbaseES sys_bulkload数据加载工具错误处理

    一.关于sys_bulkload数据加载工具 sys_bulkload是KingbaseES提供的快速加载数据的命令行工具.用户使用sys_bulkload工具能够把一定格式的文本数据简单.快速的加载 ...

  8. 一个可以让你有更多时间摸鱼的WPF控件(一)

    前言 我们平时在开发软件的过程中,有这样一类比较常见的功能,它没什么技术含量,开发起来也没有什么成就感,但是你又不得不花大量的时间来处理它,它就是对数据的增删改查.当我们每增加一个需求就需要对应若干个 ...

  9. #SPFA#洛谷 4042 [AHOI2014/JSOI2014] 骑士游戏

    题目 分析 如果我想普通攻击1,那么必须干掉所有产生的其它怪兽,这不由得可以用一个不等式来表示, \(普攻+\sum need<法攻\) 但是所需要消灭的怪兽同样可以这样进行,所以它可能具有后效 ...

  10. OpenHarmony社区运营报告(2023年7月)

     本月快讯 • 2023年7月28日-29日,全球软件质量&效能大会(简称"QECon")圆满举行,OpenAtom OpenHarmony(简称"OpenHar ...