Browse Source

Disallow selectors with trailing /template/.

It's an invalid selector: what does `Button /template/` select?
pull/8263/head
Steven Kirk 4 years ago
parent
commit
002377044a
  1. 16
      src/Avalonia.Base/Styling/Style.cs
  2. 72
      tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs
  3. 7
      tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs

16
src/Avalonia.Base/Styling/Style.cs

@ -7,6 +7,8 @@ namespace Avalonia.Styling
/// </summary>
public class Style : StyleBase
{
private Selector? _selector;
/// <summary>
/// Initializes a new instance of the <see cref="Style"/> class.
/// </summary>
@ -26,7 +28,11 @@ namespace Avalonia.Styling
/// <summary>
/// Gets or sets the style's selector.
/// </summary>
public Selector? Selector { get; set; }
public Selector? Selector
{
get => _selector;
set => _selector = ValidateSelector(value);
}
public override SelectorMatchResult TryAttach(IStyleable target, object? host)
{
@ -88,5 +94,13 @@ namespace Avalonia.Styling
base.SetParent(parent);
}
private static Selector? ValidateSelector(Selector? selector)
{
if (selector is TemplateSelector)
throw new InvalidOperationException(
"Invalid selector: Template selector must be followed by control selector.");
return selector;
}
}
}

72
tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs

@ -150,78 +150,6 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.False(sink.Active);
}
[Fact(Skip = "Template selectors a the end of nesting parent selectors currently broken")]
public void Template_Nesting_OfType_Matches()
{
var control = new Control1 { Classes = { "foo" } };
var button = new Button
{
Template = new FuncControlTemplate((x, _) => control),
};
button.ApplyTemplate();
Style nested;
var parent = new Style(x => x.OfType<Button>().Template())
{
Children =
{
(nested = new Style(x => x.Nesting().OfType<Control1>())),
}
};
var match = nested.Selector.Match(control, parent);
Assert.Equal(SelectorMatchResult.AlwaysThisInstance, match.Result);
}
[Fact]
public void Template_Nesting_OfType_Class_Matches()
{
var control = new Control1 { Classes = { "foo" } };
var button = new Button
{
Template = new FuncControlTemplate((x, _) => control),
};
button.ApplyTemplate();
Style nested;
var parent = new Style(x => x.OfType<Button>().Template())
{
Children =
{
(nested = new Style(x => x.Nesting().OfType<Control1>().Class("foo"))),
}
};
var match = nested.Selector.Match(control, parent);
Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
}
[Fact(Skip = "Template selectors a the end of nesting parent selectors currently broken")]
public void Class_Template_Nesting_OfType_Matches()
{
var control = new Control1 { Classes = { "foo" } };
var button = new Button
{
Template = new FuncControlTemplate((x, _) => control),
};
button.ApplyTemplate();
Style nested;
var parent = new Style(x => x.OfType<Button>().Class("bar").Template())
{
Children =
{
(nested = new Style(x => x.Nesting().OfType<Control1>())),
}
};
var match = nested.Selector.Match(control, parent);
Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
}
[Fact]
public void Or_Nesting_Class_Matches()
{

7
tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs

@ -69,6 +69,13 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.Equal("Foo", target.Foo);
}
[Fact]
public void Should_Throw_For_Selector_With_Trailing_Template_Selector()
{
Assert.Throws<InvalidOperationException>(() =>
new Style(x => x.OfType<Button>().Template()));
}
[Fact]
public void Style_With_No_Selector_Should_Not_Apply_To_Other_Control()
{

Loading…
Cancel
Save