Browse Source

Don't share style instances with Or selector. (#13969)

* Added failing test for #13910.

* Don't share style instances with Or selector.

Fixes #13910.
release/11.0.7
Steven Kirk 2 years ago
committed by Max Katz
parent
commit
da28a6e418
  1. 2
      src/Avalonia.Base/Styling/ControlTheme.cs
  2. 2
      src/Avalonia.Base/Styling/Style.cs
  3. 10
      src/Avalonia.Base/Styling/StyleBase.cs
  4. 39
      tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs

2
src/Avalonia.Base/Styling/ControlTheme.cs

@ -48,7 +48,7 @@ namespace Avalonia.Styling
if (HasSettersOrAnimations && TargetType.IsAssignableFrom(StyledElement.GetStyleKey(target)))
{
Attach(target, null, type);
Attach(target, null, type, true);
return SelectorMatchResult.AlwaysThisType;
}

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

@ -74,7 +74,7 @@ namespace Avalonia.Styling
if (match.IsMatch)
{
Attach(target, match.Activator, type);
Attach(target, match.Activator, type, Selector is not OrSelector);
}
result = match.Result;

10
src/Avalonia.Base/Styling/StyleBase.cs

@ -92,20 +92,24 @@ namespace Avalonia.Styling
return false;
}
internal ValueFrame Attach(StyledElement target, IStyleActivator? activator, FrameType type)
internal ValueFrame Attach(
StyledElement target,
IStyleActivator? activator,
FrameType type,
bool canShareInstance)
{
if (target is not AvaloniaObject ao)
throw new InvalidOperationException("Styles can only be applied to AvaloniaObjects.");
StyleInstance instance;
if (_sharedInstance is not null)
if (_sharedInstance is not null && canShareInstance)
{
instance = _sharedInstance;
}
else
{
var canShareInstance = activator is null;
canShareInstance &= activator is null;
instance = new StyleInstance(this, activator, type);

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

@ -1029,6 +1029,28 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.Equal(Brushes.Blue, border.Background);
}
[Fact]
public void Should_Not_Share_Instance_When_Or_Selector_Is_Present()
{
// Issue #13910
Style style = new Style(x => Selectors.Or(x.OfType<Class1>(), x.OfType<Class2>().Class("bar")))
{
Setters =
{
new Setter(Class1.FooProperty, "Foo"),
},
};
var target1 = new Class1 { Classes = { "foo" } };
var target2 = new Class2();
StyleHelpers.TryAttach(style, target1);
StyleHelpers.TryAttach(style, target2);
Assert.Equal("Foo", target1.Foo);
Assert.Equal("foodefault", target2.Foo);
}
private class Class1 : Control
{
public static readonly StyledProperty<string> FooProperty =
@ -1063,5 +1085,22 @@ namespace Avalonia.Base.UnitTests.Styling
throw new NotImplementedException();
}
}
private class Class2 : Control
{
public static readonly StyledProperty<string> FooProperty =
Class1.FooProperty.AddOwner<Class2>();
public string Foo
{
get { return GetValue(FooProperty); }
set { SetValue(FooProperty, value); }
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
}
}
}
}

Loading…
Cancel
Save