Hi all,
While refactoring our global resources from the application XAML into separate resource dictionaries, I recently discovered that our one dynamic style does not appear to properly load when using the MergedDictionaries
-tag to re-insert the now separate resource dictionaries into the application XAML as global resources. That is, UI-controls that formerly had their Style
-attribute set to {DynamicResource MyDynamicStyle}
now no longer pick up on changed to values within "MyDynamicStyle", while styles defined (page) locally and inheriting from the dynamic style using the BaseResourceKey
-attribute do observe the changes.
Has anybody else experienced this? Is this expected behaviour? Personally, I strongly suspect this is a bug...
History
Once upon a time our App had a very big monolithic UI-assembly in which all pages, renderers, UI-controls and XAML-extensions lived happily along-side each other. Then, one day, the solution's main developer decided that in order for others to more easily work together on the solution, it would be a good idea to separate the code into various smaller assemblies. This led to problems with XAML-IntelliSense in some UI-assemblies, as the application XAML was placed in the topmost-level assembly and lower-lying assemblies could therefore not access the styling at design time. No problems were experienced at runtime, however.
What's been done
In order to enable the IntelliSense and hopefully resolve some issues one of our developers is experiencing with certain styles not being found at random moments, I've decided to split the application's resource dictionary up into separate dictionaries that can each be included in the assembly they are most closely associated with. This way higher-level assemblies should, in one way or another, have access to the styles from lower-level assemblies (at least in concept).
The result is the following partitioning (from lowest-level to highest-level assembly:
1. Style-assembly "Constants"-dictionary: contains constants used in XAML; "TextStyles"-dictionary: contains both implicit and explicit (i.e. named) text styles.
2. Xaml-assembly "Converters"-dictionary: defines the IValueConverters
available to the App.
3. Controls-assembly "MyControlStyle"-dictionary: styling for the MyControl
UI-control and contains the dynamic style.
4. Pages-assembly application dictionary: combines all other dictionaries using MergedDictionaries
.
Each of the dictionaries is initializing properly using a code-behind that calls InitializeComponent
from the constructor.
Dictionaries are merged as follows:
<?xml version="1.0" encoding="utf-8" ?>
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:styling="clr-namespace:Styling.Xaml;assembly=Styling"
xmlns:converters="clr-namespace:Xaml.Converters;assembly=Xaml"
xmlns:controls="clr-namespace:Controls.Styling;assembly=Controls>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<styling:Constants />
<converters:Converters />
<styling:TextStyles />
<controls:MyControlStyle />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
The "MyControlStyle"-dictionary and dynamic style have the following set-up:
- A background colour is defined for the control, "MyControlColor";
- An implicit style is defined for the control that sets things like a font, text size, and a hard-coded default colour;
- A dynamic style is defined as "MyDynamicStyle", which uses "MyControlColor" through a
DynamicResource
-binding in the Color
-property's Setter
--tag.
"MyControlColor" is set in the App's Application
class at some point following application start, using this.Resources["MyControlColor"] = aColor;
What's observed
From the above I'd expect to just be able to continue using "MyDynamicStyle" as before. However, this is not the case. Any MyControl
that previously would get styled using the dynamic style is now no longer being styled. Except for a single instance, where "MyDynamicStyle" is used as a BaseResourceKey
to define a (page) local resource, as here changes to "MyControlColor" are being picked up.
Interestingly, if you duplicate "MyDynamicStyle" into the application resource dictionary, including the same key, everything seems to continue working fine thanks to the fallback mechanism used to resolve resources. This is no solution, though, as the above scenario is but step one in the total desired refactoring...
So why is this happening? Why are styles being treated differently when immediately included in the application resource dictionary versus when the same is done through merged dictionaries? Is this what's expected to happen?
Thanks in advance for the help! If this turns out to be a bug, I'll of course file an official bug report.
All the best,
Alexander.