/// <summary> /// ResourceDictionaryUriProperty property changed handler. /// </summary> /// <param name="dependencyObject">FrameworkElement that changed its /// ResourceDictionaryUri.</param> /// <param name="eventArgs">Event arguments.</param> private static void OnResourceDictionaryUriPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs) { FrameworkElement element = dependencyObject as FrameworkElement; if (element != null) { Uri value = (Uri)eventArgs.NewValue; ResourceDictionary resourceDictionary = null; if (value != null) { try { resourceDictionary = Parse(value); ImplicitStyleManager.SetExternalResourceDictionary(element, resourceDictionary); } catch (Exception) { element.ClearValue(ImplicitStyleManager.ExternalResourceDictionaryProperty); throw; } } else { element.ClearValue(ImplicitStyleManager.ExternalResourceDictionaryProperty); } } }
/// <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> /// Load a theme from a resource stream. /// </summary> /// <param name="themeResourceStream"> /// A resource stream containing the theme to load. /// </param> private void LoadTheme(Stream themeResourceStream) { Debug.Assert(themeResourceStream != null, "themeResourceStream should not be null!"); // Load the theme using (Stream stream = themeResourceStream) { ResourceDictionary resources = ResourceParser.Parse(stream, true); ImplicitStyleManager.SetExternalResourceDictionary(this, resources); } }
/// <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> /// ApplyModeProperty property changed handler. /// </summary> /// <param name="dependencyObject">FrameworkElement that changed its /// ApplyMode.</param> /// <param name="eventArgs">Event arguments.</param> private static void OnApplyModePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs) { FrameworkElement element = dependencyObject as FrameworkElement; if (element == null) { throw new ArgumentNullException("dependencyObject"); } ImplicitStylesApplyMode oldMode = (ImplicitStylesApplyMode)eventArgs.OldValue; ImplicitStylesApplyMode newMode = (ImplicitStylesApplyMode)eventArgs.NewValue; ImplicitStyleManager.SetHasBeenStyled(element, false); EventHandler eventHandler = ImplicitStyleManager.GetLayoutUpdatedHandler(element); // If element is automatically styled (once or always) attach event // handler. if ((newMode == ImplicitStylesApplyMode.Auto || newMode == ImplicitStylesApplyMode.OneTime) && oldMode == ImplicitStylesApplyMode.None) { if (eventHandler == null) { eventHandler = (sender, args) => { ImplicitStyleManager.PropagateStyles(element, false); }; ImplicitStyleManager.SetLayoutUpdatedHandler(element, eventHandler); element.LayoutUpdated += eventHandler; } } else if ((oldMode == ImplicitStylesApplyMode.Auto || oldMode == ImplicitStylesApplyMode.OneTime) && newMode == ImplicitStylesApplyMode.None) { if (eventHandler != null) { element.LayoutUpdated -= eventHandler; ImplicitStyleManager.SetLayoutUpdatedHandler(element, null); } } }