ControlTemplateBrowser.axaml代码
<Window xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Height="544" Width="713" Loaded="Window_Loaded" x:Class="AvaloniaUI.ControlTemplateBrowser" Title="ControlTemplateBrowser"> <Grid Margin="10" x:Name="grid" ColumnDefinitions="2*,5*"> <ListBox x:Name="lstTypes" Background="WhiteSmoke" SelectionChanged="lstTypes_SelectionChanged"> </ListBox> <Grid Grid.Column="1" RowDefinitions="*,Auto" Margin="5"> <ScrollViewer> <TextBox x:Name="txtTemplate" TextWrapping="Wrap" AcceptsReturn="True" IsReadOnly="True" FontFamily="Consolas" FontSize="13" /> </ScrollViewer> <!-- 控件预览区 --> <Border Grid.Row="1" BorderBrush="#DDD" BorderThickness="1" CornerRadius="6" Margin="0,10,0,0" Padding="10" Background="{DynamicResource ThemeBackgroundBrush}"> <ContentPresenter x:Name="previewHost" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Border> </Grid> </Grid> </Window>
ControlTemplateBrowser.axaml.cs代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Chrome;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Styling;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace AvaloniaUI;
public partial class ControlTemplateBrowser : Window
{
public ControlTemplateBrowser()
{
InitializeComponent();
}
private readonly Dictionary<string, Type> typeMap = new(StringComparer.Ordinal);
private void Window_Loaded(object? sender, RoutedEventArgs e)
{
try
{
var asmNames = new[]
{
"Avalonia.Controls",
"Avalonia.Controls.Primitives",
"Avalonia.Controls.Shapes",
"Avalonia.Controls.DataGrid",
"Avalonia.Controls.ItemsRepeater",
"Avalonia.Controls.Documents"
};
var controlType = typeof(Control);
var topLevel = typeof(TopLevel);
foreach (var name in asmNames)
{
Assembly? asm = null;
try { asm = Assembly.Load(name); } catch { continue; }
foreach (var t in asm.GetTypes())
if (t.IsPublic && !t.IsAbstract &&
controlType.IsAssignableFrom(t) &&
!topLevel.IsAssignableFrom(t) &&
!typeMap.ContainsKey(t.Name))
typeMap[t.Name] = t;
}
lstTypes.ItemsSource = typeMap.Keys.OrderBy(n => n).ToList();
}
catch (Exception ex)
{
txtTemplate.Text = "加载失败:" + ex.Message;
}
}
private void lstTypes_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (lstTypes.SelectedItem is not string name || !typeMap.TryGetValue(name, out var type))
return;
previewHost.Content = null;
try
{
if (type.GetConstructor(Type.EmptyTypes)?.Invoke(null) is not Control control)
{
txtTemplate.Text = $"<< 无法实例化 {name} >>";
return;
}
// 如果控件具有 Content 属性,设置默认文本“预览Abc”
var contentProp = type.GetProperty("Content", BindingFlags.Public | BindingFlags.Instance);
if (contentProp != null && contentProp.CanWrite && contentProp.PropertyType == typeof(object))
contentProp.SetValue(control, "预览Abc");
// 将控件显示在预览区
previewHost.Content = control;
control.Arrange(new Rect(control.DesiredSize));
control.UpdateLayout();
var sb = new StringBuilder();
sb.AppendLine($"🔹 {type.FullName}, {type.Assembly.GetName().Name}");
sb.AppendLine("──────── 模板(视觉树结构) ────────");
if (control is TemplatedControl templated && templated.Template != null)
{
var root = templated.Template.Build(templated)!.Result;
// 内联递归打印结构
void print(Control c, int d)
{
sb.AppendLine(new string(' ', d * 2) + c.GetType().Name);
if (c is Panel p) foreach (var child in p.Children) print(child, d + 1);
else if (c is ContentControl cc && cc.Content is Control c1) print(c1, d + 1);
else if (c is Decorator dc && dc.Child is Control c2) print(c2, d + 1);
}
print(root, 0);
}
else
{
sb.AppendLine("<< 控件不是 TemplatedControl 或模板为空 >>");
}
txtTemplate.Text = sb.ToString();
}
catch (Exception ex)
{
txtTemplate.Text = "<< 出错: " + ex.Message + " >>";
}
}
}
运行效果

浙公网安备 33010602011771号