dotnet UNO 如何在调试下输出界面层级结构
本文将告诉大家如何在 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 如何在调试下输出界面层级结构的更多相关文章
- 痞子衡嵌入式:浅析IAR下调试信息输出机制之硬件UART外设
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之硬件UART外设. 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我们可以比较容易地 ...
- 痞子衡嵌入式:浅析IAR下调试信息输出机制之半主机(Semihosting)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR下调试信息输出机制之半主机(Semihosting). 在嵌入式世界里,输出打印信息是一种非常常用的辅助调试手段,借助打印信息,我 ...
- 利用 Serial Over Lan(SOL)搭建 XEN 的调试信息输出环境
如有转载,请注明出处与本文连接,谢谢! 修改XEN的源码实现额外的功能,需要有一个调试环境来得到XEN的调试信息(有关源码编译并安装 XEN 请阅读我以前的博文:在CentOS下源码安装 Xen并搭建 ...
- Anjuta 调试无输出 warning: GDB: Failed to set controlling terminal
调试无输出,起初以为是那个warning的问题,后来才知道这个系统printf直到遇到'\n'换行符才输出,VC6用习惯了没想到还有这样的,网上说这样是节省系统资源. 那个warning暂时还没看到影 ...
- 关于VS中的调试信息输出
有时候一些项目的调试信息不方便输出到界面中,比如ASP.NET或者WPF之类的 可以使用Debug.WriteLine()等方法输出到"输出"窗口,不过"输出" ...
- 第七课 GDB调试 (下)
1序言: 通过前面一节第六课 GDB调试 (下)文章,可以掌握理解了gdb调试:怎么启动.运行,打断点.查看变量.甚至改变变量等的知识,今天来大概讲解下调试bug的类型. 2知识点: 2.1 就像之前 ...
- 使用 DML 自定义调试器输出
调试器标记语言 (DML) 提供了一种机制增强来自调试器和扩展的输出. 与 HTML 类似,调试器的标记支持允许将输出包括显示指令和额外非显示的标记窗体中的信息. 调试器用户界面,WinDbg 等中分 ...
- 点击TableView中某行进入下一级界面(Swift)
TableView这个控件在iOS的开发中非常的常见,他可以较好的展示一个层级结构.这里主要介绍,在点击某个条目的时候,如何进行跳转的下一个界面.以下是官方的关于这个跳转如何去实现,和如何去传递数据的 ...
- PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么?
PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么? 代码如下: <?php $arr = array('one','two','three'); fo ...
- windows下VC界面 DIY系列1----写给想要写界面的C++程序猿的话
非常早就想写关于C++ UI开发的一系列博文,博客专栏刚审核通过,就立即開始刷博文,不能辜负自己的一番热血,我并非写界面的高手,仅仅想通过写博文提高我自己的技术积累,也顺便帮助大家解决界面开发的瓶颈. ...
随机推荐
- JDBC反序列化
JDBC反序列化攻击 介绍 JDBC(Java DataBase Connectivity)是一种用于执行Sql语句的Java Api,即Java数据库连接,是Java语言中用来规范客户端程序如何来访 ...
- oracle_fdw扩展使用中异常问题
Oracle_fdw 的使用介绍已经在之前的文章中介绍过了,具体见:https://www.cnblogs.com/kingbase/p/14846479.html. 本篇文章介绍一下可能碰到的问题处 ...
- KingbaseESV8R6延迟提交参数
前言 队列理论在我们生活中的应用随处可见,例如我们去食堂打饭需要排队,我们生活中随处可见排队的场景. 在计算机领域中,性能诊断等地方使用队列理论的案例也很多.服务器硬件分为动态设备和静态设备.CPU和 ...
- 表的唯一约束的作用 KingbaseES VS Oracle
背景 演示唯一约束怎样创建.删除.禁用和使用唯一性约束,已经多种数据库的差异. 什么是唯一约束 唯一性约束指表中一个字段或者多个字段联合起来可以唯一标识一条记录的约束, 字段中,可以包括空值. 唯一性 ...
- Ant Design Vue Tree 选中子节点同时半选中父级节点
需要实现的效果: 1.子菜单如果不是全部选中,一级菜单半选. 2.子菜单全选,一级菜单选中. 3.一级菜单选择,二级菜单全选. 4.没有二级菜单,则只控制一级菜单. 主要用到的属性是checked和h ...
- 【已解决】MySQL数据库8.0版本 连接失败错误码1251
错误原因: 是mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password 解决方式: 1. cmd 进入 ...
- Android为按钮Button添加事件
匿名内部类 1 <!--匿名内部类方式--> 2 <Button 3 android:id="@+id/btn2" 4 android:layout_width= ...
- 详解SSL证书系列(8)了解HTTPS及和HTTP的区别
上一篇我们介绍了HTTP协议的三大缺点,那么怎么避免和解决HTTP的缺点呢,是时候请出我们的HTTPS了,那HTTPS和HTTP有什么区别呢? HTTP加上加密处理和认证以及完整性保护后即是HTTPS ...
- #树状数组#洛谷 5677 [GZOI2017]配对统计
题目 分析 考虑处理出所有右端点的能够匹配的左端点,然后用树状数组离线查询 代码 #include <cstdio> #include <cctype> #include &l ...
- #莫比乌斯反演#ZOJ 3435 Ideal Puzzle Bobble SP7001 VLATTICE
ZOJ 3435 Ideal Puzzle Bobble SP7001 VLATTICE - Visible Lattice Points(洛谷题目传送门) SP7001 VLATTICE - Vis ...