本文将告诉大家如何在 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. Android富文本开发

    基础概念目录介绍 01.业务需求简单介绍 02.实现的方案介绍 03.异常状态下保存状态信息 04.处理软键盘回删按钮逻辑 05.在指定位置插入图片 06.在指定位置插入输入文字 07.如果对选中文字 ...

  2. flume采集nginx日志文件数据到Kafka

    flume官网地址http://flume.apache.org/ #下载 wget https://mirrors.bfsu.edu.cn/apache/flume/1.9.0/apache-flu ...

  3. 分析性能差的sql

    --EXECUTIONS 所有子游标的执行这条语句次数 --DISK_READS 所有子游标运行这条语句导致的读磁盘次数 --BUFFER_GETS 所有子游标运行这条语句导致的读内存次数 --Hit ...

  4. java读写txt

    /** * 传入txt路径读取txt文件 * * @param txtPath * @return 返回读取到的内容 */ public String readTxt(String txtPath) ...

  5. 基于quartus的FPGA学习系列

    基于quartus学习 1.学习目标 quartus是altera的FPGA设计软件,用起来的感觉要比xilinx快.这里可以使用其完成各种基本的设计(就是不使用非必须IP核),一些基础的实验都可以在 ...

  6. 分享本人依照NOI大纲整理的CSPJ复习资料

    2023 CSP-J 复习文件 考纲 复习好 : 基础知识与编程环境 难度 计算机的基本构成 计算机的组成及功能 - 知乎 (zhihu.com) 操作系统的基本概念与常见操作 操作系统基础知识大汇总 ...

  7. 3D Object Detection Essay Reading 2024.04.05

    EMIFF 论文:https://arxiv.org/abs/2303.10975 代码:https://github.com/Bosszhe/EMIFF ​ 本文提出了一种新的基于摄像机的三维检测框 ...

  8. #倍增,LCA,Kruskal#JZOJ 1092 洛谷 4180 [BJOI 2010] 次小生成树

    题目 给出一个无向图,问它的严格次小生成树(数据保证有解) 分析 首先先找一棵最小生成树,然后对于每条非树边\((x,y,w)\)可以找到最小生成树上\(x,y\)路径上略小于\(w\),首先如果能找 ...

  9. #高精度,排列组合、dp#JZOJ 2755 树的计数

    题目 求\(n\)个点直径为\(d\)的标号树个数(多组数据) (\(0\leq d\leq n\leq 50,n>0\)) 分析 首先特判一下\(n==d\)无解,\(d=0\)除非只有一个点 ...

  10. 使用OHOS SDK构建libpng

    参照OHOS IDE和SDK的安装方法配置好开发环境. 从github下载源码. 执行如下命令: git clone --depth=1 https://github.com/glennrp/libp ...