diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
index 1ca7be67a7..46af0c81f5 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
@@ -65,6 +65,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
new AvaloniaXamlIlCompiledBindingsMetadataRemover()
);
+ Transformers.Add(new AvaloniaXamlIlControlTemplatePriorityTransformer());
Transformers.Add(new AvaloniaXamlIlMetadataRemover());
Transformers.Add(new AvaloniaXamlIlRootObjectScope());
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs
new file mode 100644
index 0000000000..22f1a8bc00
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs
@@ -0,0 +1,37 @@
+using System.Linq;
+using XamlX.Ast;
+using XamlX.Transform;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
+{
+ ///
+ /// Transforms property assignments within ControlTemplates to use Style priority where possible.
+ ///
+ class AvaloniaXamlIlControlTemplatePriorityTransformer : IXamlAstTransformer
+ {
+ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
+ {
+ var bindingPriorityType = context.GetAvaloniaTypes().BindingPriority;
+
+ if (node is XamlPropertyAssignmentNode prop &&
+ prop.Property is XamlIlAvaloniaProperty avaloniaProperty &&
+ context.ParentNodes().Any(IsControlTemplate))
+ {
+ // If there are any setters which accept a binding priority, then add the Style
+ // binding priority as a value.
+ if (avaloniaProperty.Setters.Any(x => x.Parameters[0] == bindingPriorityType))
+ {
+ prop.Values.Insert(0, new XamlConstantNode(node, bindingPriorityType, 1));
+ }
+ }
+
+ return node;
+ }
+
+ private static bool IsControlTemplate(IXamlAstNode node)
+ {
+ return node is AvaloniaXamlIlTargetTypeMetadataNode tt &&
+ tt.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.ControlTemplate;
+ }
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
index 89b88790dc..eb3b7b8f7e 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
@@ -15,6 +15,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType AvaloniaObjectExtensions { get; }
public IXamlType AvaloniaProperty { get; }
public IXamlType AvaloniaPropertyT { get; }
+ public IXamlType StyledPropertyT { get; }
public IXamlType AvaloniaAttachedPropertyT { get; }
public IXamlType IBinding { get; }
public IXamlMethod AvaloniaObjectBindMethod { get; }
@@ -94,6 +95,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
AvaloniaObjectExtensions = cfg.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions");
AvaloniaProperty = cfg.TypeSystem.GetType("Avalonia.AvaloniaProperty");
AvaloniaPropertyT = cfg.TypeSystem.GetType("Avalonia.AvaloniaProperty`1");
+ StyledPropertyT = cfg.TypeSystem.GetType("Avalonia.StyledProperty`1");
AvaloniaAttachedPropertyT = cfg.TypeSystem.GetType("Avalonia.AttachedProperty`1");
BindingPriority = cfg.TypeSystem.GetType("Avalonia.Data.BindingPriority");
IBinding = cfg.TypeSystem.GetType("Avalonia.Data.IBinding");
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
index 7f1b8caf0d..6c61ad0705 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
@@ -189,7 +189,13 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
CustomAttributes = original.CustomAttributes;
if (!original.CustomAttributes.Any(ca => ca.Type.Equals(types.AssignBindingAttribute)))
Setters.Insert(0, new BindingSetter(types, original.DeclaringType, field));
-
+
+ if (field.FieldType.GenericTypeDefinition == types.StyledPropertyT)
+ {
+ var propertyType = field.FieldType.GenericArguments[0];
+ Setters.Insert(1, new SetValueWithPrioritySetter(types, original.DeclaringType, field, propertyType));
+ }
+
Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
}
@@ -240,6 +246,39 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
+ class SetValueWithPrioritySetter : AvaloniaPropertyCustomSetter
+ {
+ public SetValueWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty,
+ IXamlType propertyType)
+ : base(types, declaringType, avaloniaProperty)
+ {
+ Parameters = new[] { types.BindingPriority, propertyType };
+ }
+
+ public override void Emit(IXamlILEmitter emitter)
+ {
+ var method = Types.AvaloniaObject
+ .FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
+ && m.Parameters.Count == 3
+ && m.Parameters[0].Name == "StyledPropertyBase`1"
+ && m.Parameters[2].Equals(Types.BindingPriority));
+
+ if (method == null)
+ throw new XamlTypeSystemException(
+ $"Unable to find AvaloniaObject.SetValue(StyledPropertyBase, T, BindingPriority).");
+
+ method = method.MakeGenericMethod(new[] { Parameters[1] });
+
+ using (var bloc = emitter.LocalsPool.GetLocal(Parameters[1]))
+ emitter
+ .Stloc(bloc.Local)
+ .Ldsfld(AvaloniaProperty)
+ .Ldloc(bloc.Local)
+ .Ldc_I4(0)
+ .EmitCall(method, true);
+ }
+ }
+
class UnsetValueSetter : AvaloniaPropertyCustomSetter
{
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)