diff --git a/src/Perspex.Styling/Styling/IStyle.cs b/src/Perspex.Styling/Styling/IStyle.cs index e8821349dd..4404853bf0 100644 --- a/src/Perspex.Styling/Styling/IStyle.cs +++ b/src/Perspex.Styling/Styling/IStyle.cs @@ -9,9 +9,12 @@ namespace Perspex.Styling public interface IStyle { /// - /// Attaches the style to a control if the style matches. + /// Attaches the style to a control if the style's selector matches. /// /// The control to attach to. - void Attach(IStyleable control); + /// + /// The control that contains this style. May be null. + /// + void Attach(IStyleable control, IStyleHost container); } } diff --git a/src/Perspex.Styling/Styling/Style.cs b/src/Perspex.Styling/Styling/Style.cs index c8f4144977..f32856187e 100644 --- a/src/Perspex.Styling/Styling/Style.cs +++ b/src/Perspex.Styling/Styling/Style.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Reactive.Linq; namespace Perspex.Styling { @@ -41,16 +42,29 @@ namespace Perspex.Styling /// Attaches the style to a control if the style's selector matches. /// /// The control to attach to. - public void Attach(IStyleable control) + /// + /// The control that contains this style. May be null. + /// + public void Attach(IStyleable control, IStyleHost container) { - var description = "Style " + Selector.ToString(); - var match = Selector.Match(control); + if (Selector != null) + { + var description = "Style " + Selector.ToString(); + var match = Selector.Match(control); - if (match.ImmediateResult != false) + if (match.ImmediateResult != false) + { + foreach (var setter in Setters) + { + setter.Apply(this, control, match.ObservableResult); + } + } + } + else if (control == container) { foreach (var setter in Setters) { - setter.Apply(this, control, match.ObservableResult); + setter.Apply(this, control, null); } } } @@ -61,7 +75,14 @@ namespace Perspex.Styling /// A string representation of the style. public override string ToString() { - return "Style: " + Selector.ToString(); + if (Selector != null) + { + return "Style: " + Selector.ToString(); + } + else + { + return "Style"; + } } } } diff --git a/src/Perspex.Styling/Styling/Styler.cs b/src/Perspex.Styling/Styling/Styler.cs index c129b90908..67f8bc537f 100644 --- a/src/Perspex.Styling/Styling/Styler.cs +++ b/src/Perspex.Styling/Styling/Styler.cs @@ -21,7 +21,7 @@ namespace Perspex.Styling if (global != null) { - global.Styles.Attach(control); + global.Styles.Attach(control, null); } if (styleContainer != null) @@ -50,7 +50,7 @@ namespace Perspex.Styling } } - container.Styles.Attach(control); + container.Styles.Attach(control, container); } private IStyleHost GetParentContainer(IStyleHost container) diff --git a/src/Perspex.Styling/Styling/Styles.cs b/src/Perspex.Styling/Styling/Styles.cs index 2ebf858cd6..877235a337 100644 --- a/src/Perspex.Styling/Styling/Styles.cs +++ b/src/Perspex.Styling/Styling/Styles.cs @@ -5,13 +5,23 @@ using Perspex.Collections; namespace Perspex.Styling { + /// + /// A style that consists of a number of child styles. + /// public class Styles : PerspexList, IStyle { - public void Attach(IStyleable control) + /// + /// Attaches the style to a control if the style's selector matches. + /// + /// The control to attach to. + /// + /// The control that contains this style. May be null. + /// + public void Attach(IStyleable control, IStyleHost container) { foreach (IStyle style in this) { - style.Attach(control); + style.Attach(control, container); } } } diff --git a/tests/Perspex.Styling.UnitTests/StyleTests.cs b/tests/Perspex.Styling.UnitTests/StyleTests.cs index 8ab7c786ab..cda975b597 100644 --- a/tests/Perspex.Styling.UnitTests/StyleTests.cs +++ b/tests/Perspex.Styling.UnitTests/StyleTests.cs @@ -24,7 +24,7 @@ namespace Perspex.Styling.UnitTests var target = new Class1(); - style.Attach(target); + style.Attach(target, null); Assert.Equal("Foo", target.Foo); } @@ -42,7 +42,7 @@ namespace Perspex.Styling.UnitTests var target = new Class1(); - style.Attach(target); + style.Attach(target, null); Assert.Equal("foodefault", target.Foo); target.Classes.Add("foo"); Assert.Equal("Foo", target.Foo); @@ -50,6 +50,43 @@ namespace Perspex.Styling.UnitTests Assert.Equal("foodefault", target.Foo); } + [Fact] + public void Style_With_No_Selector_Should_Apply_To_Containing_Control() + { + Style style = new Style + { + Setters = new[] + { + new Setter(Class1.FooProperty, "Foo"), + }, + }; + + var target = new Class1(); + + style.Attach(target, target); + + Assert.Equal("Foo", target.Foo); + } + + [Fact] + public void Style_With_No_Selector_Should_Not_Apply_To_Other_Control() + { + Style style = new Style + { + Setters = new[] + { + new Setter(Class1.FooProperty, "Foo"), + }, + }; + + var target = new Class1(); + var other = new Class1(); + + style.Attach(target, other); + + Assert.Equal("foodefault", target.Foo); + } + [Fact] public void LocalValue_Should_Override_Style() { @@ -66,7 +103,7 @@ namespace Perspex.Styling.UnitTests Foo = "Original", }; - style.Attach(target); + style.Attach(target, null); Assert.Equal("Original", target.Foo); } @@ -97,7 +134,7 @@ namespace Perspex.Styling.UnitTests List values = new List(); target.GetObservable(Class1.FooProperty).Subscribe(x => values.Add(x)); - styles.Attach(target); + styles.Attach(target, null); target.Classes.Add("foo"); target.Classes.Remove("foo"); @@ -119,7 +156,7 @@ namespace Perspex.Styling.UnitTests var target = new Class1(); - style.Attach(target); + style.Attach(target, null); Assert.Equal("Foo", target.Foo); } @@ -139,7 +176,7 @@ namespace Perspex.Styling.UnitTests var target = new Class1(); - style.Attach(target); + style.Attach(target, null); Assert.Equal("foodefault", target.Foo); target.Classes.Add("foo");