Skip to content

Commit 05d348b

Browse files
authored
Merge pull request #11575 from workgroupengineering/features/Issue_11334
feat: Also allows using string instead of {x:Type} in ControlTemplate.TargetType
2 parents 0f93224 + c428ff3 commit 05d348b

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Linq;
22
using XamlX.Ast;
33
using XamlX.Transform;
4+
using XamlX.Transform.Transformers;
45
using XamlX.TypeSystem;
56

67
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
@@ -22,26 +23,19 @@ public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode nod
2223
IXamlAstTypeReference targetType;
2324

2425
var templatableBaseType = context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control");
25-
26-
if ((tt?.Values.FirstOrDefault() is XamlTypeExtensionNode tn))
27-
{
28-
targetType = tn.Value;
29-
}
30-
else
26+
27+
targetType = tt?.Values.FirstOrDefault() switch
3128
{
32-
var parentScope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>()
33-
.FirstOrDefault();
34-
if (parentScope?.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style)
35-
targetType = parentScope.TargetType;
36-
else if (context.ParentNodes().Skip(1).FirstOrDefault() is XamlAstObjectNode directParentNode
37-
&& templatableBaseType.IsAssignableFrom(directParentNode.Type.GetClrType()))
38-
targetType = directParentNode.Type;
39-
else
40-
targetType = new XamlAstClrTypeReference(node,
41-
templatableBaseType, false);
42-
}
43-
44-
29+
XamlTypeExtensionNode tn => tn.Value,
30+
XamlAstTextNode textNode => TypeReferenceResolver.ResolveType(context, textNode.Text, false, textNode, true),
31+
_ when context.ParentNodes()
32+
.OfType<AvaloniaXamlIlTargetTypeMetadataNode>()
33+
.FirstOrDefault() is { ScopeType: AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style } parentScope => parentScope.TargetType,
34+
_ when context.ParentNodes().Skip(1).FirstOrDefault() is XamlAstObjectNode directParentNode
35+
&& templatableBaseType.IsAssignableFrom(directParentNode.Type.GetClrType()) => directParentNode.Type,
36+
_ => new XamlAstClrTypeReference(node,
37+
templatableBaseType, false)
38+
};
4539

4640
return new AvaloniaXamlIlTargetTypeMetadataNode(on, targetType,
4741
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.ControlTemplate);
@@ -59,7 +53,7 @@ public enum ScopeTypes
5953
ControlTemplate,
6054
Transitions
6155
}
62-
56+
6357
public AvaloniaXamlIlTargetTypeMetadataNode(IXamlAstValueNode value, IXamlAstTypeReference targetType,
6458
ScopeTypes type)
6559
: base(value, value)

tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,24 @@ public void ControlTemplate_With_TargetType_Is_Operational()
286286
Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Result);
287287
}
288288

289+
[Fact]
290+
public void ControlTemplate_With_String_TargetType()
291+
{
292+
var xaml = @"
293+
<ControlTemplate xmlns='https://github.com/avaloniaui'
294+
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
295+
TargetType='ContentControl'>
296+
<ContentPresenter Content='{TemplateBinding Content}' />
297+
</ControlTemplate>
298+
";
299+
var template = AvaloniaRuntimeXamlLoader.Parse<ControlTemplate>(xaml);
300+
301+
Assert.Equal(typeof(ContentControl), template.TargetType);
302+
303+
Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Result);
304+
}
305+
306+
289307
[Fact]
290308
public void ControlTemplate_With_Panel_Children_Are_Added()
291309
{

0 commit comments

Comments
 (0)