Browse Source

Merge pull request #11575 from workgroupengineering/features/Issue_11334

feat: Also allows using string instead of {x:Type} in ControlTemplate.TargetType
release/11.0.5-rc1
Max Katz 3 years ago
committed by Steven Kirk
parent
commit
2ec0e4ba77
  1. 34
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer.cs
  2. 18
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs

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

@ -1,6 +1,7 @@
using System.Linq;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
@ -22,26 +23,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
IXamlAstTypeReference targetType;
var templatableBaseType = context.Configuration.TypeSystem.GetType("Avalonia.Controls.Control");
if ((tt?.Values.FirstOrDefault() is XamlTypeExtensionNode tn))
{
targetType = tn.Value;
}
else
targetType = tt?.Values.FirstOrDefault() switch
{
var parentScope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>()
.FirstOrDefault();
if (parentScope?.ScopeType == AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style)
targetType = parentScope.TargetType;
else if (context.ParentNodes().Skip(1).FirstOrDefault() is XamlAstObjectNode directParentNode
&& templatableBaseType.IsAssignableFrom(directParentNode.Type.GetClrType()))
targetType = directParentNode.Type;
else
targetType = new XamlAstClrTypeReference(node,
templatableBaseType, false);
}
XamlTypeExtensionNode tn => tn.Value,
XamlAstTextNode textNode => TypeReferenceResolver.ResolveType(context, textNode.Text, false, textNode, true),
_ when context.ParentNodes()
.OfType<AvaloniaXamlIlTargetTypeMetadataNode>()
.FirstOrDefault() is { ScopeType: AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style } parentScope => parentScope.TargetType,
_ when context.ParentNodes().Skip(1).FirstOrDefault() is XamlAstObjectNode directParentNode
&& templatableBaseType.IsAssignableFrom(directParentNode.Type.GetClrType()) => directParentNode.Type,
_ => new XamlAstClrTypeReference(node,
templatableBaseType, false)
};
return new AvaloniaXamlIlTargetTypeMetadataNode(on, targetType,
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.ControlTemplate);
@ -59,7 +53,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
ControlTemplate,
Transitions
}
public AvaloniaXamlIlTargetTypeMetadataNode(IXamlAstValueNode value, IXamlAstTypeReference targetType,
ScopeTypes type)
: base(value, value)

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

@ -286,6 +286,24 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Result);
}
[Fact]
public void ControlTemplate_With_String_TargetType()
{
var xaml = @"
<ControlTemplate xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
TargetType='ContentControl'>
<ContentPresenter Content='{TemplateBinding Content}' />
</ControlTemplate>
";
var template = AvaloniaRuntimeXamlLoader.Parse<ControlTemplate>(xaml);
Assert.Equal(typeof(ContentControl), template.TargetType);
Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Result);
}
[Fact]
public void ControlTemplate_With_Panel_Children_Are_Added()
{

Loading…
Cancel
Save