diff --git a/src/Avalonia.Styling/Styling/ChildSelector.cs b/src/Avalonia.Styling/Styling/ChildSelector.cs
index bcbf358721..8b1d2a8553 100644
--- a/src/Avalonia.Styling/Styling/ChildSelector.cs
+++ b/src/Avalonia.Styling/Styling/ChildSelector.cs
@@ -24,6 +24,9 @@ namespace Avalonia.Styling
///
public override bool InTemplate => _parent.InTemplate;
+ ///
+ public override bool IsCombinator => true;
+
///
public override Type TargetType => null;
@@ -43,11 +46,24 @@ namespace Avalonia.Styling
if (controlParent != null)
{
- return _parent.Match((IStyleable)controlParent, subscribe);
+ var parentMatch = _parent.Match((IStyleable)controlParent, subscribe);
+
+ if (parentMatch.Result == SelectorMatchResult.Sometimes)
+ {
+ return parentMatch;
+ }
+ else if (parentMatch.IsMatch)
+ {
+ return SelectorMatch.AlwaysThisInstance;
+ }
+ else
+ {
+ return SelectorMatch.NeverThisInstance;
+ }
}
else
{
- return SelectorMatch.False;
+ return SelectorMatch.NeverThisInstance;
}
}
diff --git a/src/Avalonia.Styling/Styling/DescendentSelector.cs b/src/Avalonia.Styling/Styling/DescendentSelector.cs
index 943b3f0161..a81908f23d 100644
--- a/src/Avalonia.Styling/Styling/DescendentSelector.cs
+++ b/src/Avalonia.Styling/Styling/DescendentSelector.cs
@@ -22,6 +22,9 @@ namespace Avalonia.Styling
_parent = parent;
}
+ ///
+ public override bool IsCombinator => true;
+
///
public override bool InTemplate => _parent.InTemplate;
@@ -51,16 +54,13 @@ namespace Avalonia.Styling
{
var match = _parent.Match((IStyleable)c, subscribe);
- if (match.ImmediateResult != null)
+ if (match.Result == SelectorMatchResult.Sometimes)
{
- if (match.ImmediateResult == true)
- {
- return SelectorMatch.True;
- }
+ descendantMatches.Add(match.Activator);
}
- else
+ else if (match.IsMatch)
{
- descendantMatches.Add(match.ObservableResult);
+ return SelectorMatch.AlwaysThisInstance;
}
}
}
@@ -71,7 +71,7 @@ namespace Avalonia.Styling
}
else
{
- return SelectorMatch.False;
+ return SelectorMatch.NeverThisInstance;
}
}
diff --git a/src/Avalonia.Styling/Styling/IStyle.cs b/src/Avalonia.Styling/Styling/IStyle.cs
index 3cf8491ae3..da2a08f04d 100644
--- a/src/Avalonia.Styling/Styling/IStyle.cs
+++ b/src/Avalonia.Styling/Styling/IStyle.cs
@@ -17,7 +17,12 @@ namespace Avalonia.Styling
///
/// The control that contains this style. May be null.
///
- void Attach(IStyleable control, IStyleHost container);
+ ///
+ /// True if the style can match a control of type
+ /// (even if it does not match this control specifically); false if the style
+ /// can never match.
+ ///
+ bool Attach(IStyleable control, IStyleHost container);
void Detach();
}
diff --git a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs
index 541e8646b1..cfc0998fe0 100644
--- a/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs
+++ b/src/Avalonia.Styling/Styling/PropertyEqualsSelector.cs
@@ -30,6 +30,9 @@ namespace Avalonia.Styling
///
public override bool InTemplate => _previous?.InTemplate ?? false;
+ ///
+ public override bool IsCombinator => false;
+
///
/// Gets the name of the control to match.
///
@@ -78,7 +81,8 @@ namespace Avalonia.Styling
}
else
{
- return new SelectorMatch((control.GetValue(_property) ?? string.Empty).Equals(_value));
+ var result = (control.GetValue(_property) ?? string.Empty).Equals(_value);
+ return result ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance;
}
}
diff --git a/src/Avalonia.Styling/Styling/Selector.cs b/src/Avalonia.Styling/Styling/Selector.cs
index 24c6be9b7a..af209ea970 100644
--- a/src/Avalonia.Styling/Styling/Selector.cs
+++ b/src/Avalonia.Styling/Styling/Selector.cs
@@ -17,6 +17,14 @@ namespace Avalonia.Styling
///
public abstract bool InTemplate { get; }
+ ///
+ /// Gets a value indicating whether this selector is a combinator.
+ ///
+ ///
+ /// A combinator is a selector such as Child or Descendent which links simple selectors.
+ ///
+ public abstract bool IsCombinator { get; }
+
///
/// Gets the target type of the selector, if available.
///
@@ -33,25 +41,32 @@ namespace Avalonia.Styling
/// A .
public SelectorMatch Match(IStyleable control, bool subscribe = true)
{
- List> inputs = new List>();
- Selector selector = this;
+ var inputs = new List>();
+ var selector = this;
+ var alwaysThisType = true;
+ var hitCombinator = false;
while (selector != null)
{
- if (selector.InTemplate && control.TemplatedParent == null)
- {
- return SelectorMatch.False;
- }
+ hitCombinator |= selector.IsCombinator;
var match = selector.Evaluate(control, subscribe);
- if (match.ImmediateResult == false)
+ if (!match.IsMatch)
+ {
+ return hitCombinator ? SelectorMatch.NeverThisInstance : match;
+ }
+ else if (selector.InTemplate && control.TemplatedParent == null)
+ {
+ return SelectorMatch.NeverThisInstance;
+ }
+ else if (match.Result == SelectorMatchResult.AlwaysThisInstance)
{
- return match;
+ alwaysThisType = false;
}
- else if (match.ObservableResult != null)
+ else if (match.Result == SelectorMatchResult.Sometimes)
{
- inputs.Add(match.ObservableResult);
+ inputs.Add(match.Activator);
}
selector = selector.MovePrevious();
@@ -63,7 +78,9 @@ namespace Avalonia.Styling
}
else
{
- return SelectorMatch.True;
+ return alwaysThisType && !hitCombinator ?
+ SelectorMatch.AlwaysThisType :
+ SelectorMatch.AlwaysThisInstance;
}
}
diff --git a/src/Avalonia.Styling/Styling/SelectorMatch.cs b/src/Avalonia.Styling/Styling/SelectorMatch.cs
index f325578389..63b89e9e97 100644
--- a/src/Avalonia.Styling/Styling/SelectorMatch.cs
+++ b/src/Avalonia.Styling/Styling/SelectorMatch.cs
@@ -5,51 +5,95 @@ using System;
namespace Avalonia.Styling
{
+ ///
+ /// Describes how a matches a control and its type.
+ ///
+ public enum SelectorMatchResult
+ {
+ ///
+ /// The selector never matches this type.
+ ///
+ NeverThisType,
+
+ ///
+ /// The selector never matches this instance, but can match this type.
+ ///
+ NeverThisInstance,
+
+ ///
+ /// The selector always matches this type.
+ ///
+ AlwaysThisType,
+
+ ///
+ /// The selector always matches this instance, but doesn't always match this type.
+ ///
+ AlwaysThisInstance,
+
+ ///
+ /// The selector matches this instance based on the .
+ ///
+ Sometimes,
+ }
+
///
/// Holds the result of a match.
///
///
- /// There are two types of selectors - ones whose match can never change for a particular
- /// control (such as ) and ones whose result can
- /// change over time (such as . For the first
- /// category of selectors, the value of will be set but for the
- /// second, will be null and will
- /// hold an observable which tracks the match.
+ /// A selector match describes whether and how a matches a control, and
+ /// in addition whether the selector can ever match a control of the same type.
///
public class SelectorMatch
{
- public static readonly SelectorMatch False = new SelectorMatch(false);
+ ///
+ /// A selector match with the result of .
+ ///
+ public static readonly SelectorMatch NeverThisType = new SelectorMatch(SelectorMatchResult.NeverThisType);
- public static readonly SelectorMatch True = new SelectorMatch(true);
+ ///
+ /// A selector match with the result of .
+ ///
+ public static readonly SelectorMatch NeverThisInstance = new SelectorMatch(SelectorMatchResult.NeverThisInstance);
///
- /// Initializes a new instance of the class.
+ /// A selector match with the result of .
///
- /// The immediate match value.
- public SelectorMatch(bool match)
- {
- ImmediateResult = match;
- }
+ public static readonly SelectorMatch AlwaysThisType = new SelectorMatch(SelectorMatchResult.AlwaysThisType);
///
- /// Initializes a new instance of the class.
+ /// Gets a selector match with the result of .
///
- /// The observable match value.
+ public static readonly SelectorMatch AlwaysThisInstance = new SelectorMatch(SelectorMatchResult.AlwaysThisInstance);
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// result.
+ ///
+ /// The match activator.
public SelectorMatch(IObservable match)
{
- ObservableResult = match;
+ Contract.Requires(match != null);
+
+ Result = SelectorMatchResult.Sometimes;
+ Activator = match;
}
+ private SelectorMatch(SelectorMatchResult result) => Result = result;
+
///
- /// Gets the immediate result of the selector match, in the case of selectors that cannot
- /// change over time.
+ /// Gets a value indicating whether the match was positive.
+ ///
+ public bool IsMatch => Result >= SelectorMatchResult.AlwaysThisType;
+
+ ///
+ /// Gets the result of the match.
///
- public bool? ImmediateResult { get; }
+ public SelectorMatchResult Result { get; }
///
/// Gets an observable which tracks the selector match, in the case of selectors that can
/// change over time.
///
- public IObservable ObservableResult { get; }
+ public IObservable Activator { get; }
}
}
diff --git a/src/Avalonia.Styling/Styling/Style.cs b/src/Avalonia.Styling/Styling/Style.cs
index 23c318a809..27fad58346 100644
--- a/src/Avalonia.Styling/Styling/Style.cs
+++ b/src/Avalonia.Styling/Styling/Style.cs
@@ -106,20 +106,14 @@ namespace Avalonia.Styling
///
bool IResourceProvider.HasResources => _resources?.Count > 0;
- ///
- /// 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)
+ ///
+ public bool Attach(IStyleable control, IStyleHost container)
{
if (Selector != null)
{
var match = Selector.Match(control);
- if (match.ImmediateResult != false)
+ if (match.IsMatch)
{
var controlSubscriptions = GetSubscriptions(control);
@@ -129,9 +123,10 @@ namespace Avalonia.Styling
{
foreach (var animation in Animations)
{
- IObservable obsMatch = match.ObservableResult;
+ var obsMatch = match.Activator;
- if (match.ImmediateResult == true)
+ if (match.Result == SelectorMatchResult.AlwaysThisType ||
+ match.Result == SelectorMatchResult.AlwaysThisInstance)
{
obsMatch = Observable.Return(true);
}
@@ -143,13 +138,15 @@ namespace Avalonia.Styling
foreach (var setter in Setters)
{
- var sub = setter.Apply(this, control, match.ObservableResult);
+ var sub = setter.Apply(this, control, match.Activator);
subs.Add(sub);
}
controlSubscriptions.Add(subs);
Subscriptions.Add(subs);
}
+
+ return match.Result != SelectorMatchResult.NeverThisType;
}
else if (control == container)
{
@@ -165,7 +162,10 @@ namespace Avalonia.Styling
controlSubscriptions.Add(subs);
Subscriptions.Add(subs);
+ return true;
}
+
+ return false;
}
///
diff --git a/src/Avalonia.Styling/Styling/Styles.cs b/src/Avalonia.Styling/Styling/Styles.cs
index 22ed8bb241..51499b737a 100644
--- a/src/Avalonia.Styling/Styling/Styles.cs
+++ b/src/Avalonia.Styling/Styling/Styles.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
+using System.Collections.Generic;
using System.Linq;
using Avalonia.Collections;
using Avalonia.Controls;
@@ -15,6 +16,7 @@ namespace Avalonia.Styling
{
private IResourceNode _parent;
private IResourceDictionary _resources;
+ private Dictionary> _cache;
public Styles()
{
@@ -34,6 +36,7 @@ namespace Avalonia.Styling
}
x.ResourcesChanged += SubResourceChanged;
+ _cache = null;
},
x =>
{
@@ -49,6 +52,7 @@ namespace Avalonia.Styling
}
x.ResourcesChanged -= SubResourceChanged;
+ _cache = null;
},
() => { });
}
@@ -97,11 +101,46 @@ namespace Avalonia.Styling
///
/// The control that contains this style. May be null.
///
- public void Attach(IStyleable control, IStyleHost container)
+ public bool Attach(IStyleable control, IStyleHost container)
{
- foreach (IStyle style in this)
+ if (_cache == null)
+ {
+ _cache = new Dictionary>();
+ }
+
+ if (_cache.TryGetValue(control.StyleKey, out var cached))
+ {
+ if (cached != null)
+ {
+ foreach (var style in cached)
+ {
+ style.Attach(control, container);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+ else
{
- style.Attach(control, container);
+ List result = null;
+
+ foreach (var style in this)
+ {
+ if (style.Attach(control, container))
+ {
+ if (result == null)
+ {
+ result = new List();
+ }
+
+ result.Add(style);
+ }
+ }
+
+ _cache.Add(control.StyleKey, result);
+ return result != null;
}
}
diff --git a/src/Avalonia.Styling/Styling/TemplateSelector.cs b/src/Avalonia.Styling/Styling/TemplateSelector.cs
index 6919b4ad27..7530339883 100644
--- a/src/Avalonia.Styling/Styling/TemplateSelector.cs
+++ b/src/Avalonia.Styling/Styling/TemplateSelector.cs
@@ -23,6 +23,9 @@ namespace Avalonia.Styling
///
public override bool InTemplate => true;
+ ///
+ public override bool IsCombinator => true;
+
///
public override Type TargetType => null;
@@ -46,7 +49,7 @@ namespace Avalonia.Styling
"Cannot call Template selector on control with null TemplatedParent.");
}
- return _parent.Match(templatedParent, subscribe) ?? SelectorMatch.True;
+ return _parent.Match(templatedParent, subscribe);
}
protected override Selector MovePrevious() => null;
diff --git a/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs b/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
index 94c0b75c6e..cd019e6535 100644
--- a/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
+++ b/src/Avalonia.Styling/Styling/TypeNameAndClassSelector.cs
@@ -68,6 +68,9 @@ namespace Avalonia.Styling
///
public override Type TargetType => _targetType ?? _previous?.TargetType;
+ ///
+ public override bool IsCombinator => false;
+
///
/// Whether the selector matches the concrete or any object which
/// implements .
@@ -101,21 +104,23 @@ namespace Avalonia.Styling
{
if (controlType != TargetType)
{
- return SelectorMatch.False;
+ return SelectorMatch.NeverThisType;
}
}
else
{
if (!TargetType.GetTypeInfo().IsAssignableFrom(controlType.GetTypeInfo()))
{
- return SelectorMatch.False;
+ return SelectorMatch.NeverThisType;
}
}
}
- if (Name != null && control.Name != Name)
+ if (Name != null)
{
- return SelectorMatch.False;
+ return control.Name == Name ?
+ SelectorMatch.AlwaysThisInstance :
+ SelectorMatch.NeverThisInstance;
}
if (_classes.IsValueCreated && _classes.Value.Count > 0)
@@ -127,12 +132,14 @@ namespace Avalonia.Styling
}
else
{
- return new SelectorMatch(Matches(control.Classes));
+ return Matches(control.Classes) ?
+ SelectorMatch.AlwaysThisInstance :
+ SelectorMatch.NeverThisInstance;
}
}
else
{
- return SelectorMatch.True;
+ return SelectorMatch.AlwaysThisType;
}
}
diff --git a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
index fc2656f236..9273011cb9 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
@@ -62,12 +62,14 @@ namespace Avalonia.Markup.Xaml.Styling
IResourceNode IResourceNode.ResourceParent => _parent;
///
- public void Attach(IStyleable control, IStyleHost container)
+ public bool Attach(IStyleable control, IStyleHost container)
{
if (Source != null)
{
- Loaded.Attach(control, container);
+ return Loaded.Attach(control, container);
}
+
+ return false;
}
public void Detach()
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
index d837f2cb2f..0561837ad1 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Child.cs
@@ -27,7 +27,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Child().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -42,7 +42,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Child().OfType();
- Assert.False(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -54,7 +54,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Child().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
var result = new List();
Assert.False(await activator.Take(1));
@@ -70,7 +70,7 @@ namespace Avalonia.Styling.UnitTests
var control = new TestLogical3();
var selector = default(Selector).OfType().Child().OfType();
- Assert.False(selector.Match(control).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.NeverThisInstance, selector.Match(control).Result);
}
[Fact]
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
index 75599925b7..496998ecd9 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Class.cs
@@ -40,9 +40,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.True(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.True(await match.Activator.Take(1));
}
[Fact]
@@ -54,9 +55,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.False(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.False(await match.Activator.Take(1));
}
[Fact]
@@ -69,9 +71,10 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var match = target.Match(control);
- Assert.True(await activator.Take(1));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ Assert.True(await match.Activator.Take(1));
}
[Fact]
@@ -80,7 +83,7 @@ namespace Avalonia.Styling.UnitTests
var control = new Control1();
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
@@ -96,7 +99,7 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.True(await activator.Take(1));
control.Classes.Remove("foo");
@@ -108,7 +111,7 @@ namespace Avalonia.Styling.UnitTests
{
var control = new Control1();
var target = default(Selector).Class("foo").Class("bar");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
Assert.False(await activator.Take(1));
control.Classes.Add("foo");
@@ -129,7 +132,7 @@ namespace Avalonia.Styling.UnitTests
};
var target = default(Selector).Class("foo");
- var activator = target.Match(control).ObservableResult;
+ var activator = target.Match(control).Activator;
var result = new List();
using (activator.Subscribe(x => result.Add(x)))
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
index b75b59c212..56dad13186 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Descendent.cs
@@ -26,7 +26,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Descendant().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -41,7 +41,7 @@ namespace Avalonia.Styling.UnitTests
var selector = default(Selector).OfType().Descendant().OfType();
- Assert.True(selector.Match(child).ImmediateResult);
+ Assert.Equal(SelectorMatchResult.AlwaysThisInstance, selector.Match(child).Result);
}
[Fact]
@@ -56,7 +56,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.True(await activator.Take(1));
}
@@ -74,7 +74,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.False(await activator.Take(1));
}
@@ -90,7 +90,7 @@ namespace Avalonia.Styling.UnitTests
child.LogicalParent = parent;
var selector = default(Selector).OfType().Class("foo").Descendant().OfType();
- var activator = selector.Match(child).ObservableResult;
+ var activator = selector.Match(child).Activator;
Assert.False(await activator.Take(1));
parent.Classes.Add("foo");
diff --git a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
index 067b08b296..04b29376b0 100644
--- a/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
+++ b/tests/Avalonia.Styling.UnitTests/SelectorTests_Multiple.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Styling.UnitTests
public class SelectorTests_Multiple
{
[Fact]
- public void Template_Child_Of_Control_With_Two_Classes()
+ public void Named_Template_Child_Of_Control_With_Two_Classes()
{
var template = new FuncControlTemplate(parent =>
{
@@ -40,9 +40,10 @@ namespace Avalonia.Styling.UnitTests
var border = (Border)((IVisual)control).VisualChildren.Single();
var values = new List();
- var activator = selector.Match(border).ObservableResult;
+ var match = selector.Match(border);
- activator.Subscribe(x => values.Add(x));
+ Assert.Equal(SelectorMatchResult.Sometimes, match.Result);
+ match.Activator.Subscribe(x => values.Add(x));
Assert.Equal(new[] { false }, values);
control.Classes.AddRange(new[] { "foo", "bar" });
@@ -51,6 +52,39 @@ namespace Avalonia.Styling.UnitTests
Assert.Equal(new[] { false, true, false }, values);
}
+ [Fact]
+ public void Named_OfType_Template_Child_Of_Control_With_Two_Classes_Wrong_Type()
+ {
+ var template = new FuncControlTemplate(parent =>
+ {
+ return new Border
+ {
+ Name = "border",
+ };
+ });
+
+ var control = new Button
+ {
+ Template = template,
+ };
+
+ control.ApplyTemplate();
+
+ var selector = default(Selector)
+ .OfType