5 changed files with 155 additions and 21 deletions
@ -0,0 +1,39 @@ |
|||
using System.Linq; |
|||
using XamlX; |
|||
using XamlX.Ast; |
|||
using XamlX.Transform; |
|||
using XamlX.Transform.Transformers; |
|||
using XamlX.TypeSystem; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers |
|||
{ |
|||
class AvaloniaXamlIlControlThemeTransformer : IXamlAstTransformer |
|||
{ |
|||
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) |
|||
{ |
|||
if (!(node is XamlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.ControlTheme")) |
|||
return node; |
|||
|
|||
// Check if we've already transformed this node.
|
|||
if (context.ParentNodes().FirstOrDefault() is AvaloniaXamlIlTargetTypeMetadataNode) |
|||
return node; |
|||
|
|||
var targetTypeNode = on.Children.OfType<XamlAstXamlPropertyValueNode>() |
|||
.FirstOrDefault(p => p.Property.GetClrProperty().Name == "TargetType") ?? |
|||
throw new XamlParseException("ControlTheme must have a TargetType.", node); |
|||
|
|||
IXamlType targetType; |
|||
|
|||
if (targetTypeNode.Values[0] is XamlTypeExtensionNode extension) |
|||
targetType = extension.Value.GetClrType(); |
|||
else if (targetTypeNode.Values[0] is XamlAstTextNode text) |
|||
targetType = TypeReferenceResolver.ResolveType(context, text.Text, false, text, true).GetClrType(); |
|||
else |
|||
throw new XamlParseException("Could not determine TargetType for ControlTheme.", targetTypeNode); |
|||
|
|||
return new AvaloniaXamlIlTargetTypeMetadataNode(on, |
|||
new XamlAstClrTypeReference(targetTypeNode, targetType, false), |
|||
AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.Media; |
|||
using Avalonia.UnitTests; |
|||
using Avalonia.VisualTree; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Markup.Xaml.UnitTests.Xaml |
|||
{ |
|||
public class ControlThemeTests : XamlTestBase |
|||
{ |
|||
[Fact] |
|||
public void ControlTheme_Can_Be_StaticResource() |
|||
{ |
|||
using (UnitTestApplication.Start(TestServices.StyledWindow)) |
|||
{ |
|||
var xaml = $@"
|
|||
<Window xmlns='https://github.com/avaloniaui'
|
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
|||
xmlns:u='using:Avalonia.Markup.Xaml.UnitTests.Xaml'> |
|||
<Window.Resources> |
|||
{ControlThemeXaml} |
|||
</Window.Resources> |
|||
|
|||
<u:TestTemplatedControl Theme='{{StaticResource MyTheme}}'/> |
|||
</Window>";
|
|||
|
|||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml); |
|||
var button = Assert.IsType<TestTemplatedControl>(window.Content); |
|||
|
|||
window.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
Assert.NotNull(button.Template); |
|||
|
|||
var child = Assert.Single(button.GetVisualChildren()); |
|||
var border = Assert.IsType<Border>(child); |
|||
|
|||
Assert.Equal(Brushes.Red, border.Background); |
|||
} |
|||
} |
|||
|
|||
private const string ControlThemeXaml = @"
|
|||
<ControlTheme x:Key='MyTheme' TargetType='u:TestTemplatedControl'> |
|||
<Setter Property='Template'> |
|||
<ControlTemplate> |
|||
<Border/> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
<Style Selector='^ /template/ Border'> |
|||
<Setter Property='Background' Value='Red'/> |
|||
</Style> |
|||
</ControlTheme>";
|
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using Avalonia.Controls.Primitives; |
|||
|
|||
namespace Avalonia.Markup.Xaml.UnitTests.Xaml |
|||
{ |
|||
public class TestTemplatedControl : TemplatedControl |
|||
{ |
|||
} |
|||
} |
|||
Loading…
Reference in new issue