/// <summary> /// Tries to match the selector with a control. /// </summary> /// <param name="control">The control.</param> /// <param name="subscribe"> /// Whether the match should subscribe to changes in order to track the match over time, /// or simply return an immediate result. /// </param> /// <returns>A <see cref="SelectorMatch"/>.</returns> public SelectorMatch Match(IStyleable control, bool subscribe = true) { List <IObservable <bool> > inputs = new List <IObservable <bool> >(); Selector selector = this; while (selector != null) { if (selector.InTemplate && control.TemplatedParent == null) { return(SelectorMatch.False); } var match = selector.Evaluate(control, subscribe); if (match.ImmediateResult == false) { return(match); } else if (match.ObservableResult != null) { inputs.Add(match.ObservableResult); } selector = selector.MovePrevious(); } if (inputs.Count > 0) { return(new SelectorMatch(StyleActivator.And(inputs))); } else { return(SelectorMatch.True); } }
private static SelectorMatchResult Match( IStyleable control, Selector selector, IStyle?parent, bool subscribe, ref AndActivatorBuilder activators, ref Selector?combinator) { var previous = selector.MovePrevious(); // Selectors are stored from right-to-left, so we recurse into the selector in order to // reverse this order, because the type selector will be on the left and is our best // opportunity to exit early. if (previous != null && !previous.IsCombinator) { var previousMatch = Match(control, previous, parent, subscribe, ref activators, ref combinator); if (previousMatch < SelectorMatchResult.Sometimes) { return(previousMatch); } } // Match this selector. var match = selector.Evaluate(control, parent, subscribe); if (!match.IsMatch) { combinator = null; return(match.Result); } else if (match.Activator is object) { activators.Add(match.Activator !); } if (previous?.IsCombinator == true) { combinator = previous; } return(match.Result); }