Primary WinUI APIs:
Primary Avalonia APIs:
| WinUI idiom | Avalonia idiom |
|---|---|
template part contract (PART_*) |
template part contract (PART_*) |
GetTemplateChild lookup |
NameScope.Find<T> lookup |
VisualStateManager.GoToState |
pseudo-class toggles + selectors/transitions |
| default template in generic styles | default ControlTheme |
WinUI XAML:
<ControlTemplate TargetType="local:StatusBadge">
<Border x:Name="PART_Indicator" />
</ControlTemplate>
WinUI C#:
[TemplatePart(Name = "PART_Indicator", Type = typeof(Border))]
public sealed class StatusBadge : Control
{
private Border? _indicator;
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
_indicator = GetTemplateChild("PART_Indicator") as Border;
VisualStateManager.GoToState(this, IsWarning ? "Warning" : "Normal", false);
}
}
Avalonia XAML:
<ControlTheme xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Controls"
TargetType="local:StatusBadge">
<Setter Property="Template">
<ControlTemplate>
<Border x:Name="PART_Indicator" />
</ControlTemplate>
</Setter>
</ControlTheme>
<Style Selector="local|StatusBadge:warning /template/ Border#PART_Indicator">
<Setter Property="Background" Value="OrangeRed" />
</Style>
Avalonia C#:
public class StatusBadge : TemplatedControl
{
public static readonly StyledProperty<bool> IsWarningProperty =
AvaloniaProperty.Register<StatusBadge, bool>(nameof(IsWarning));
private Border? _indicator;
public bool IsWarning
{
get => GetValue(IsWarningProperty);
set => SetValue(IsWarningProperty, value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
_indicator = e.NameScope.Find<Border>("PART_Indicator");
PseudoClasses.Set(":warning", IsWarning);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsWarningProperty)
PseudoClasses.Set(":warning", IsWarning);
}
}
PART_* contracts stable and documented during migration.