/// <summary> /// Retrieves or creates the merged style dictionary of an element. /// </summary> /// <param name="styledElement">A styled element.</param> /// <returns>The merged dictionary of the element.</returns> private static BaseMergedStyleDictionary GetMergedStyleDictionary(FrameworkElement styledElement) { Debug.Assert(styledElement != null, "styledElement cannot be null."); IList <FrameworkElement> ancestorsInclusive = styledElement.GetVisualAncestors().Append(styledElement).Reverse().ToList(); IEnumerable <FrameworkElement> ancestorsTopToBottom = ancestorsInclusive; BaseMergedStyleDictionary initialDictionary = null; if (UseApplicationResources) { initialDictionary = new MergedStyleResourceDictionary(ApplicationExternalResourceDictionary ?? Application.Current.Resources); } else { FrameworkElement topLevelElement = ancestorsInclusive[0]; initialDictionary = new MergedStyleResourceDictionary(ImplicitStyleManager.GetExternalResourceDictionary(topLevelElement) ?? topLevelElement.Resources); ancestorsTopToBottom = ancestorsInclusive.Skip(1); } BaseMergedStyleDictionary styleDictionary = ancestorsTopToBottom.Aggregate( initialDictionary, (dictionary, ancestor) => new MergedStyleResourceDictionary(ImplicitStyleManager.GetExternalResourceDictionary(ancestor) ?? ancestor.Resources) { Parent = dictionary }); return(styleDictionary); }
/// <summary> /// This method propagates the styles in the resources associated with /// a framework element to its descendents. This results in a /// style inheritance that mimics WPF's behavior. /// </summary> /// <param name="element">The element that will have its styles /// propagated to its children.</param> /// <param name="recurse">Whether to recurse over styled elements that /// are set to OneTime and have already been styled.</param> private static void PropagateStyles(FrameworkElement element, bool recurse) { BaseMergedStyleDictionary initialDictionary = GetMergedStyleDictionary(element); // Create stream of elements and their base merged style // dictionaries by traversing the logical tree. IEnumerable <Tuple <FrameworkElement, BaseMergedStyleDictionary> > elementsToStyleAndDictionaries = FunctionalProgramming.TraverseDepthFirst( new Tuple <FrameworkElement, BaseMergedStyleDictionary>(element, initialDictionary), (elementAndDictionary) => elementAndDictionary .First .GetLogicalChildrenDepthFirst() .Select(childElement => new Tuple <FrameworkElement, BaseMergedStyleDictionary>( childElement, new MergedStyleResourceDictionary( ImplicitStyleManager.GetExternalResourceDictionary(childElement) ?? childElement.Resources, elementAndDictionary.Second))), (elementAndDictionary) => recurse || (ImplicitStyleManager.GetApplyMode(elementAndDictionary.First) != ImplicitStylesApplyMode.OneTime || !ImplicitStyleManager.GetHasBeenStyled(elementAndDictionary.First))); foreach (Tuple <FrameworkElement, BaseMergedStyleDictionary> elementToStyleAndDictionary in elementsToStyleAndDictionaries) { FrameworkElement elementToStyle = elementToStyleAndDictionary.First; BaseMergedStyleDictionary styleDictionary = elementToStyleAndDictionary.Second; bool styleApplied = false; if (elementToStyle.Style == null || GetStyle(elementToStyle) == elementToStyle.Style) { Style style = styleDictionary[GetStyleKey(elementToStyle)]; if (style != null) { SetStyle(elementToStyle, style); styleApplied = true; } } if (ImplicitStyleManager.GetApplyMode(elementToStyle) == ImplicitStylesApplyMode.OneTime && (VisualTreeHelper.GetChildrenCount(elementToStyle) > 0 || styleApplied)) { ImplicitStyleManager.SetHasBeenStyled(elementToStyle, true); } } }
/// <summary> /// Initializes a new instance of the MergedResourceDictionary class. /// </summary> /// <param name="resourceDictionary">A resource dictionary to check for /// a value before checking the parent.</param> /// <param name="parentResourceDictionary">The parent merged resource /// dictionary to check if no match is found in the resource /// dictionary.</param> public MergedStyleResourceDictionary(ResourceDictionary resourceDictionary, BaseMergedStyleDictionary parentResourceDictionary) { Debug.Assert(resourceDictionary != null, "resourceDictionary cannot be null."); _resourceDictionary = resourceDictionary; Parent = parentResourceDictionary; }