Browse Source

Use style priority for attached values in templates.

pull/7679/head
Steven Kirk 5 years ago
parent
commit
351be2f4b2
  1. 14
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs
  2. 5
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  3. 66
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs

14
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlControlTemplatePriorityTransformer.cs

@ -15,12 +15,19 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
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
// - There's just a direct call setter available
if (node is XamlPropertyAssignmentNode prop &&
prop.Property is XamlIlAvaloniaProperty avaloniaProperty &&
context.ParentNodes().Any(IsControlTemplate))
context.ParentNodes().Any(IsControlTemplate) &&
prop.PossibleSetters.Count == 1 &&
prop.PossibleSetters[0] is XamlDirectCallPropertySetter)
{
// If there are any setters which accept a binding priority, then add the Style
// binding priority as a value.
// Check if there are any setters on the property which accept a binding priority -
// this filters the candidates down to styled and attached properties. If so, then
// use this setter with BindingPriority.Style.
var setPriorityValueSetter =
avaloniaProperty.Setters.FirstOrDefault(x => x.Parameters[0] == bindingPriorityType);
@ -30,6 +37,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
prop.PossibleSetters = new List<IXamlPropertySetter> { setPriorityValueSetter };
prop.Values.Insert(0, new XamlConstantNode(node, bindingPriorityType, (int)BindingPriority.Style));
return node;
}
}

5
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs

@ -190,7 +190,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
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)
// 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(1, new SetValueWithPrioritySetter(types, original.DeclaringType, field, propertyType));

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

@ -12,7 +12,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
public class ControlTemplateTests : XamlTestBase
{
[Fact]
public void Inline_ControlTemplate_Values_Are_Set_With_Style_Priority()
public void Inline_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@ -43,7 +43,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
[Fact]
public void Style_ControlTemplate_Values_Are_Set_With_Style_Priority()
public void Style_ControlTemplate_Styled_Values_Are_Set_With_Style_Priority()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
@ -76,6 +76,68 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
}
}
[Fact]
public void ControlTemplate_Attached_Values_Are_Set_With_Style_Priority()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Button>
<Button.Template>
<ControlTemplate>
<ContentPresenter Name='PART_ContentPresenter'
DockPanel.Dock='Top'/>
</ControlTemplate>
</Button.Template>
</Button>
</Window>";
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.Style, diagnostic.Priority);
}
}
[Fact]
public void ControlTemplate_TemplateBindings_Are_Set_With_TemplatedParent_Priority()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Button Content='Foo'>
<Button.Template>
<ControlTemplate>
<ContentPresenter Name='PART_ContentPresenter'
Content='{TemplateBinding Content}'/>
</ControlTemplate>
</Button.Template>
</Button>
</Window>";
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()
{

Loading…
Cancel
Save