diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
index a801d338c3..dc9064b262 100644
--- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
+++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
@@ -95,6 +95,9 @@
Markup/%(RecursiveDir)%(FileName)%(Extension)
+
+ Markup/%(RecursiveDir)%(FileName)%(Extension)
+
Markup/%(RecursiveDir)%(FileName)%(Extension)
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index b39ceab1b6..39a83c00c4 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -251,7 +251,8 @@ namespace Avalonia.Build.Tasks
var populateBuilder = classTypeDefinition == null ?
builder :
typeSystem.CreateTypeBuilder(classTypeDefinition);
- compiler.Compile(parsed, contextClass,
+ compiler.Compile(parsed,
+ contextClass,
compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
classTypeDefinition == null),
buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
index 0d41ec93b4..094cd59025 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
@@ -68,6 +68,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..6cab68e756
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using System.Linq;
+using Avalonia.Data;
+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;
+
+ // The node is a candidate for transformation if:
+ // - It's a property assignment to an Avalonia property
+ // - There's a ControlTemplate ancestor
+ // - The property has a single value
+ if (node is XamlPropertyAssignmentNode prop &&
+ prop.Property is XamlIlAvaloniaProperty avaloniaProperty &&
+ context.ParentNodes().Any(IsControlTemplate) &&
+ prop.Values.Count == 1)
+ {
+ var priorityValueSetters = new List();
+
+ // Iterate through the possible setters, trying to find a setter on the property
+ // which has a BindingPriority parameter followed by the parameter of the existing
+ // setter.
+ foreach (var setter in prop.PossibleSetters)
+ {
+ var s = avaloniaProperty.Setters.FirstOrDefault(x =>
+ x.Parameters[0] == bindingPriorityType &&
+ x.Parameters[1] == setter.Parameters[0]);
+ if (s != null)
+ priorityValueSetters.Add(s);
+ }
+
+ // If any BindingPriority setters were found, use those.
+ if (priorityValueSetters.Count > 0)
+ {
+ prop.PossibleSetters = priorityValueSetters;
+ prop.Values.Insert(0, new XamlConstantNode(node, bindingPriorityType, (int)BindingPriority.TemplatedParent));
+ }
+ }
+
+ 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 28787d9b84..9d9f6a08ab 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,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
public IXamlType AvaloniaObjectExtensions { get; }
public IXamlType AvaloniaProperty { get; }
public IXamlType AvaloniaPropertyT { get; }
+ public IXamlType StyledPropertyT { get; }
+ public IXamlMethod AvaloniaObjectSetStyledPropertyValue { get; }
public IXamlType AvaloniaAttachedPropertyT { get; }
public IXamlType IBinding { get; }
public IXamlMethod AvaloniaObjectBindMethod { get; }
@@ -105,8 +107,14 @@ 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");
+ AvaloniaObjectSetStyledPropertyValue = AvaloniaObject
+ .FindMethod(m => m.IsPublic && !m.IsStatic && m.Name == "SetValue"
+ && m.Parameters.Count == 3
+ && m.Parameters[0].Name == "StyledPropertyBase`1"
+ && m.Parameters[2].Equals(BindingPriority));
IBinding = cfg.TypeSystem.GetType("Avalonia.Data.IBinding");
IDisposable = cfg.TypeSystem.GetType("System.IDisposable");
ICommand = cfg.TypeSystem.GetType("System.Windows.Input.ICommand");
diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
index 7f1b8caf0d..5c7a80e680 100644
--- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
+++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
@@ -185,11 +185,24 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
AvaloniaXamlIlWellKnownTypes types)
:base(original, original.Name, original.DeclaringType, original.Getter, original.Setters)
{
+ var assignBinding = original.CustomAttributes.Any(ca => ca.Type.Equals(types.AssignBindingAttribute));
+
AvaloniaProperty = field;
CustomAttributes = original.CustomAttributes;
- if (!original.CustomAttributes.Any(ca => ca.Type.Equals(types.AssignBindingAttribute)))
+ if (!assignBinding)
Setters.Insert(0, new BindingSetter(types, original.DeclaringType, field));
-
+
+ // Styled and attached properties can be set with a BindingPriority when they're
+ // assigned in a ControlTemplate.
+ if (field.FieldType.GenericTypeDefinition == types.StyledPropertyT ||
+ field.FieldType.GenericTypeDefinition == types.AvaloniaAttachedPropertyT)
+ {
+ var propertyType = field.FieldType.GenericArguments[0];
+ Setters.Insert(0, new SetValueWithPrioritySetter(types, original.DeclaringType, field, propertyType));
+ if (!assignBinding)
+ Setters.Insert(1, new BindingWithPrioritySetter(types, original.DeclaringType, field));
+ }
+
Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
}
@@ -240,6 +253,63 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
+ class BindingWithPrioritySetter : AvaloniaPropertyCustomSetter
+ {
+ public BindingWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types,
+ IXamlType declaringType,
+ IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty)
+ {
+ Parameters = new[] { types.BindingPriority, types.IBinding };
+ }
+
+ public override void Emit(IXamlILEmitter emitter)
+ {
+ using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding))
+ using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int))
+ emitter
+ .Stloc(bloc.Local)
+ .Stloc(priorityLocal.Local)
+ .Ldsfld(AvaloniaProperty)
+ .Ldloc(bloc.Local)
+ // TODO: provide anchor?
+ .Ldnull();
+ emitter.EmitCall(Types.AvaloniaObjectBindMethod, true);
+ }
+ }
+
+ 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)
+ {
+ /*
+ Current stack:
+ - object
+ - binding priority
+ - value
+ */
+
+ var method = Types.AvaloniaObjectSetStyledPropertyValue
+ .MakeGenericMethod(new[] { Parameters[1] });
+
+ using (var valueLocal = emitter.LocalsPool.GetLocal(Parameters[1]))
+ using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int))
+ emitter
+ .Stloc(valueLocal.Local)
+ .Stloc(priorityLocal.Local)
+ .Ldsfld(AvaloniaProperty)
+ .Ldloc(valueLocal.Local)
+ .Ldloc(priorityLocal.Local)
+ .EmitCall(method, true);
+ }
+ }
+
class UnsetValueSetter : AvaloniaPropertyCustomSetter
{
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)
diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
index 30d321426f..d0c39f0289 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
+++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
@@ -48,6 +48,7 @@
+
diff --git a/src/Markup/Avalonia.Markup.Xaml/Extensions.cs b/src/Markup/Avalonia.Markup.Xaml/Extensions.cs
index 263750c316..d937a83010 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Extensions.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Extensions.cs
@@ -24,10 +24,10 @@ namespace Avalonia.Markup.Xaml
public static IEnumerable GetParents(this IServiceProvider sp)
{
return sp.GetService().Parents.OfType();
-
-
}
+ public static bool IsInControlTemplate(this IServiceProvider sp) => sp.GetService() != null;
+
public static Type ResolveType(this IServiceProvider ctx, string namespacePrefix, string type)
{
var tr = ctx.GetService();
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
index 087611bd59..f13ecab4e1 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/DynamicResourceExtension.cs
@@ -11,6 +11,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public class DynamicResourceExtension : IBinding
{
private object? _anchor;
+ private BindingPriority _priority;
public DynamicResourceExtension()
{
@@ -25,6 +26,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public IBinding ProvideValue(IServiceProvider serviceProvider)
{
+ if (serviceProvider.IsInControlTemplate())
+ _priority = BindingPriority.TemplatedParent;
+
var provideTarget = serviceProvider.GetService();
if (!(provideTarget.TargetObject is IStyledElement))
@@ -53,12 +57,12 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
if (control != null)
{
var source = control.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
- return InstancedBinding.OneWay(source);
+ return InstancedBinding.OneWay(source, _priority);
}
else if (_anchor is IResourceProvider resourceProvider)
{
var source = resourceProvider.GetResourceObservable(ResourceKey, GetConverter(targetProperty));
- return InstancedBinding.OneWay(source);
+ return InstancedBinding.OneWay(source, _priority);
}
return null;
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlControlTemplateProvider.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlControlTemplateProvider.cs
new file mode 100644
index 0000000000..ed3f5bfdff
--- /dev/null
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/IAvaloniaXamlIlControlTemplateProvider.cs
@@ -0,0 +1,8 @@
+using System.Collections.Generic;
+
+namespace Avalonia.Markup.Xaml.XamlIl.Runtime
+{
+ public interface IAvaloniaXamlIlControlTemplateProvider
+ {
+ }
+}
diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
index c48f386ffd..a0e7fd7dcf 100644
--- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
@@ -42,7 +42,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
class DeferredParentServiceProvider :
IAvaloniaXamlIlParentStackProvider,
IServiceProvider,
- IRootObjectProvider
+ IRootObjectProvider,
+ IAvaloniaXamlIlControlTemplateProvider
{
private readonly IServiceProvider _parentProvider;
private readonly List _parentResourceNodes;
@@ -75,6 +76,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
return this;
if (serviceType == typeof(IRootObjectProvider))
return this;
+ if (serviceType == typeof(IAvaloniaXamlIlControlTemplateProvider))
+ return this;
return _parentProvider?.GetService(serviceType);
}
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
index 9635ab285d..0bb6c01041 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs
@@ -283,70 +283,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal(expected4, grid.RowDefinitions[3].Height);
}
- [Fact]
- public void ControlTemplate_With_Nested_Child_Is_Operational()
- {
- var xaml = @"
-
-
-
-
-
-";
- var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
-
- var parent = (ContentControl)template.Build(new ContentControl()).Control;
-
- Assert.Equal("parent", parent.Name);
-
- var child = parent.Content as ContentControl;
-
- Assert.NotNull(child);
-
- Assert.Equal("child", child.Name);
- }
-
- [Fact]
- public void ControlTemplate_With_TargetType_Is_Operational()
- {
- var xaml = @"
-
-
-
-";
- var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
-
- Assert.Equal(typeof(ContentControl), template.TargetType);
-
- Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Control);
- }
-
- [Fact]
- public void ControlTemplate_With_Panel_Children_Are_Added()
- {
- var xaml = @"
-
-
-
-
-
-
-";
- var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
-
- var panel = (Panel)template.Build(new ContentControl()).Control;
-
- Assert.Equal(2, panel.Children.Count);
-
- var foo = panel.Children[0];
- var bar = panel.Children[1];
-
- Assert.Equal("Foo", foo.Name);
- Assert.Equal("Bar", bar.Name);
- }
-
[Fact]
public void Named_x_Control_Is_Added_To_NameScope_Simple()
{
@@ -363,7 +299,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
[Fact]
- public void Standart_TypeConverter_Is_Used()
+ public void Standard_TypeConverter_Is_Used()
{
var xaml = @"";
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs
new file mode 100644
index 0000000000..2d6ed1dc62
--- /dev/null
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs
@@ -0,0 +1,273 @@
+using Avalonia.Controls;
+using Avalonia.Controls.Presenters;
+using Avalonia.Data;
+using Avalonia.Diagnostics;
+using Avalonia.Markup.Xaml.Templates;
+using Avalonia.Media;
+using Avalonia.UnitTests;
+using Xunit;
+
+namespace Avalonia.Markup.Xaml.UnitTests.Xaml
+{
+ public class ControlTemplateTests : XamlTestBase
+ {
+ [Fact]
+ public void Inline_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal(Brushes.Red, presenter.Background);
+
+ var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void Style_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal(Brushes.Red, presenter.Background);
+
+ var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void ControlTemplate_Attached_Values_Are_Set_With_Style_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal(Dock.Top, DockPanel.GetDock(presenter));
+
+ var diagnostic = presenter.GetDiagnostic(DockPanel.DockProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void ControlTemplate_StaticResources_Are_Set_With_Style_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+ Red
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal(Brushes.Red, presenter.Background);
+
+ var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void ControlTemplate_DynamicResources_Are_Set_With_Style_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+ Red
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal(Brushes.Red, presenter.Background);
+
+ var diagnostic = presenter.GetDiagnostic(Button.BackgroundProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void ControlTemplate_TemplateBindings_Are_Set_With_TemplatedParent_Priority()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var xaml = @"
+
+
+";
+ var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+ var button = (Button)window.Content;
+
+ window.ApplyTemplate();
+ button.ApplyTemplate();
+
+ var presenter = (ContentPresenter)button.Presenter;
+ Assert.Equal("Foo", presenter.Content);
+
+ var diagnostic = presenter.GetDiagnostic(ContentPresenter.ContentProperty);
+ Assert.Equal(BindingPriority.TemplatedParent, diagnostic.Priority);
+ }
+ }
+
+ [Fact]
+ public void ControlTemplate_With_Nested_Child_Is_Operational()
+ {
+ var xaml = @"
+
+
+
+
+
+";
+ var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
+
+ var parent = (ContentControl)template.Build(new ContentControl()).Control;
+
+ Assert.Equal("parent", parent.Name);
+
+ var child = parent.Content as ContentControl;
+
+ Assert.NotNull(child);
+
+ Assert.Equal("child", child.Name);
+ }
+
+ [Fact]
+ public void ControlTemplate_With_TargetType_Is_Operational()
+ {
+ var xaml = @"
+
+
+
+";
+ var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
+
+ Assert.Equal(typeof(ContentControl), template.TargetType);
+
+ Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Control);
+ }
+
+ [Fact]
+ public void ControlTemplate_With_Panel_Children_Are_Added()
+ {
+ var xaml = @"
+
+
+
+
+
+
+";
+ var template = AvaloniaRuntimeXamlLoader.Parse(xaml);
+
+ var panel = (Panel)template.Build(new ContentControl()).Control;
+
+ Assert.Equal(2, panel.Children.Count);
+
+ var foo = panel.Children[0];
+ var bar = panel.Children[1];
+
+ Assert.Equal("Foo", foo.Name);
+ Assert.Equal("Bar", bar.Name);
+ }
+ }
+}