private static IList <IDomElement <TDependencyObject> > UpdateMatchingStyles( StyleSheet styleSheet, IDomElement <TDependencyObject> startFromLogical, IDomElement <TDependencyObject> startFromVisual, Dictionary <TDependencyObject, StyleUpdateInfo> styleUpdateInfos, IDependencyPropertyService <TDependencyObject, TStyle, TDependencyProperty> dependencyPropertyService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { // var requiredStyleInfos = new List<StyleMatchInfo>(); IDomElement <TDependencyObject> root = null; IDomElement <TDependencyObject> visualTree = null; IDomElement <TDependencyObject> logicalTree = null; var found = new List <IDomElement <TDependencyObject> >(); if (startFromVisual?.StyleInfo.DoMatchCheck == SelectorType.None || startFromLogical?.StyleInfo.DoMatchCheck == SelectorType.None) { return(new List <IDomElement <TDependencyObject> >()); } return($"{startFromLogical?.GetPath() ?? startFromVisual?.GetPath() ?? "NULL!?!"}".Measure(() => { foreach (var rule in styleSheet.Rules) { $"{rule.SelectorString}".Measure(() => { // // Debug.WriteLine($"--- RULE {rule.SelectorString} ----"); if (rule.SelectorType == SelectorType.VisualTree) { if (startFromVisual == null) { //continue; return; } if (visualTree == null) { visualTree = startFromVisual; visualTree?.XamlCssStyleSheets.Clear(); visualTree?.XamlCssStyleSheets.Add(styleSheet); } root = visualTree; } else { if (startFromLogical == null) { //continue; return; } if (logicalTree == null) { logicalTree = startFromLogical; logicalTree?.XamlCssStyleSheets.Clear(); logicalTree?.XamlCssStyleSheets.Add(styleSheet); } root = logicalTree; } if (root == null) { //continue; return; } // apply our selector var matchedNodes = "QuerySelectorAllWithSelf".Measure(() => root.QuerySelectorAllWithSelf(styleSheet, rule.Selectors[0]) .Where(x => x != null) .Cast <IDomElement <TDependencyObject> >() .ToList()); var matchedElementTypes = matchedNodes .Select(x => x.Element.GetType()) .Distinct() .ToList(); $"foreach {matchedNodes.Count}".Measure(() => { foreach (var matchingNode in matchedNodes) { var element = matchingNode.Element; if (!found.Contains(matchingNode)) { found.Add(matchingNode); } var discriminator = "GetInitialStyle".Measure(() => dependencyPropertyService.GetInitialStyle(element) != null ? element.GetHashCode().ToString() : ""); var resourceKey = "GetStyleResourceKey".Measure(() => nativeStyleService.GetStyleResourceKey(styleSheet.Id + discriminator, element.GetType(), rule.SelectorString)); //var resourceKey = nativeStyleService.GetStyleResourceKey(rule.StyleSheetId, element.GetType(), rule.SelectorString); if (!matchingNode.StyleInfo.CurrentMatchedSelectors.Contains(resourceKey)) { matchingNode.StyleInfo.CurrentMatchedSelectors.Add(resourceKey); } } }); }); } "found".Measure(() => { found = found.Distinct().ToList(); foreach (var f in found) { f.StyleInfo.DoMatchCheck = SelectorType.None; f.StyleInfo.CurrentMatchedSelectors = f.StyleInfo.CurrentMatchedSelectors.Distinct().Select(x => new { key = x, SpecificityResult = SpecificityCalculator.Calculate(x.Split('{')[1]) }) .OrderBy(x => x.SpecificityResult.IdSpecificity) .ThenBy(x => x.SpecificityResult.ClassSpecificity) .ThenBy(x => x.SpecificityResult.SimpleSpecificity) .ToList() .Select(x => x.key) .ToList(); } }); "SetDoMatchCheckToNoneInSubTree".Measure(() => { SetDoMatchCheckToNoneInSubTree(startFromLogical, styleSheet); SetDoMatchCheckToNoneInSubTree(startFromVisual, styleSheet); }); return found; })); }
private static void ApplyMatchingStyles(IDomElement <TDependencyObject> domElement, StyleSheet styleSheet, IStyleResourcesService applicationResourcesService, INativeStyleService <TStyle, TDependencyObject, TDependencyProperty> nativeStyleService) { var visualElement = domElement.Element; if (domElement.StyleInfo == null) { throw new Exception($"StyleInfo null {domElement.GetType().Name.Replace("DomElement", "")} {domElement.GetPath()}"); } var matchingStyles = domElement.StyleInfo.CurrentMatchedSelectors; var appliedMatchingStyles = domElement.StyleInfo.OldMatchedSelectors; var styledBy = domElement.StyleInfo.CurrentStyleSheet; if (styledBy != null && styledBy != styleSheet) { // Debug.WriteLine(" Another Stylesheet"); return; } domElement.StyleInfo.CurrentStyleSheet = styleSheet; if (!AppliedStyleIdsAreMatchedStyleIds(appliedMatchingStyles, matchingStyles)) { object styleToApply = null; if (matchingStyles == null) { // RemoveOutdatedStylesFromElementInternal(visualElement, styleSheet, true, true); } else if (matchingStyles?.Count == 1) { if (applicationResourcesService.Contains(matchingStyles[0]) == true) { styleToApply = applicationResourcesService.GetResource(matchingStyles[0]); } if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); // Debug.WriteLine(" Style not found! " + matchingStyles[0]); } } else if (matchingStyles?.Count > 1) { var dict = new Dictionary <TDependencyProperty, object>(); var listTriggers = new List <TDependencyObject>(); foreach (var matchingStyle in matchingStyles) { TStyle s = null; if (applicationResourcesService.Contains(matchingStyle) == true) { s = (TStyle)applicationResourcesService.GetResource(matchingStyle); } else { // Debug.WriteLine(" Style not found! " + matchingStyle); } if (s != null) { var subDict = nativeStyleService.GetStyleAsDictionary(s as TStyle); foreach (var i in subDict) { dict[i.Key] = i.Value; } var triggers = nativeStyleService.GetTriggersAsList(s as TStyle); listTriggers.AddRange(triggers); } } if (dict.Keys.Count > 0 || listTriggers.Count > 0) { styleToApply = nativeStyleService.CreateFrom(dict, listTriggers, visualElement.GetType()); } if (styleToApply != null) { nativeStyleService.SetStyle(visualElement, (TStyle)styleToApply); } else { nativeStyleService.SetStyle(visualElement, null); } } domElement.StyleInfo.OldMatchedSelectors = matchingStyles.ToList(); } foreach (var child in domElement.ChildNodes) { ApplyMatchingStyles(child, styleSheet, applicationResourcesService, nativeStyleService); } }