Dark/Light theme assets qualifiers - c#

I have a very simple requirement to use Light/Dark themed images. I expected that a qualifier like
SomeImage.Theme-Light.png
or putting the image under a folder named Theme-Light
Theme-Light/SomeImage.png
would work, and it did, but only in the designer mode. As soon as I run the app, even though the required theme is properly set (on both app and page level so all the other ThemeResources get loaded correctly), wrong image gets loaded.
I know about workarounds to load different images for different themes, so that's not what I'm looking for. I am curious to know why this approach with qualifiers doesn't work in runtime? Is there a different name qualifier that should be used?
I read this article: "How to name resources using qualifiers (XAML)" but it only shows how to name the assets with regards to high contrast support.

This aproach isn't as convenient as qualifiers, but it works.
Define in App.xaml
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<ImageSource x:Key="Logo">/Assets/Logo-White.png</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<ImageSource x:Key="Logo">/Assets/Logo-Blue.png</ImageSource>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<ImageSource x:Key="Logo">/Assets/Logo-White.png</ImageSource>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
Then use
<Image Source="{ThemeResource Logo}"/>

Related

Unable to Resolve Resources

I am using the MaterialDesign for XAML package in WPF. When I run my application, all styles and controls are rendered as expected. However in the XAML designer I have dozes of errors such as "The resource 'MaterialDesignFlatButton' could not be resolved." Example of a line that is throwing that error:
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 8 0" ...
My app.xaml contents is as follows:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.LightBlue.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I have attempted the top solution proposed on The resource "x" could not be resolved. but that causes the project to fail to run (I believe I am not using the correct pathing when attempting to use the proposed "absolute pack URI"). So I have two questions at this point:
Is there a reason the resources would fail to resolve in the XAML designer given the way I have defined them in App.xaml (per the developer guide: https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/Getting-Started)?
How can I find out the "absolute pack URI" to use for the source for my resource dictionaries?
In the past, I had problems like this.
The error causes are as follow.
1. Setup and setting config
About this, please check the github and material design homepage.
2. Build and Compiler problem
About this, users may set the "Platform Target" as "x64".
That can invoke errors because material designer tool use "x32" compiler, so please use "any cpu" or "x32".
I had this problem with the flat accent button, while every other button style worked. I added the resource for buttons, then the error was gone. Then I removed the button resource... and the error was still gone.
https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/wiki/FAQ
Exception: Cannot find resource named 'MaterialDesign...'
This error typically comes when you have a static resource referencing
one of the material design styles, and have not included the
appropriate resource dictionary that contains the style. Try the
following:
Ensure that you have loaded all of the default material design styles in your App.xaml. You can find directions for this in the
Getting Started guide.
Ensure you have referenced the control specific resource dictionary that contains the style. The path for this is resource dictionary
should be .xaml" />. For example, if you were trying to reference the
MaterialDesignFloatingActionMiniButton style for a button, the
resource dictionary source would be: . Typically these inclusions are done at root of your Window, User
Control, or Template. You can find the full list of the resource
dictionaries here

Am I including font using PACK URI correctly?

I want to include my fonts into application through styles. (Resource Dicitionaries) Seems like every font looks same.
I tried include these fonts using pack://application:,,,/Fonts/#font-name
Unfortunately that did not resolved my problem at all.
Fonts.xaml
<FontFamily x:Key="LatoThin">pack://application:,,,/Fonts/#Lato Thin</FontFamily>
<FontFamily x:Key="LatoRegular">pack://application:,,,/Fonts/#Lato Regular</FontFamily>
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/Fonts.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I expect every font looks like it should instead I get default font.
Ok, so I found the answer.
I found out that it works with this code.
<FontFamily x:Key="LatoThin">Fonts/Lato-Thin.ttf #Lato Thin</FontFamily>

Window style not visible in designer

I created a Window style (WPF) and added it as a dll to my project
this style shows corretly when i run the program but doesn't show up in the designer.
I googled already but none of the solutions there are working
Test 1:
// Window //
Style="{DynamicResource HVE_Window}"
// Window.Resources //
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GlobalHive.Styles;component/HiveWindow.xaml"/>
</ResourceDictionary.MergedDictionaries>
Result:
Error: 'Window' TargetType doesn not match type of element 'WindowInstance'
-> But it runs and display correctly there
Test 2:
// Window //
Style="{DynamicResource MyWindow}"
// Window.Resources //
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/GlobalHive.Styles;component/HiveWindow.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="MyWindow" TargetType="{x:Type Window}" BasedOn="{StaticResource HVE_Window}" />
Result:
No Error:
Still doesn't display in the designer, still shows up if i run the program
Test 3:
Both versions but added to application resources
How it should look:
How it looks inside the designer:
You can sometimes find that resources from a control library are not loaded at design time, despite whatever you put in app.xaml to try and load the things.
MS created a mechanism for Blend which you can use in visual studio since it's the blend designer.
This uses a "special" resource dictionary called DesignTimeResources.xaml
This will only be used at design time.
Add one to the Properties of your problem exe project.
With exactly that name.
Put all your merges into that.
eg this is one of mine from my MapEditor project that uses numerous resources from UILib. UILib is a control library with all sorts of UI stuff in it.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MapEditor">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/UILib;component/Resources/Geometries.xaml"/>
<ResourceDictionary Source="pack://application:,,,/UILib;component/Resources/ControlTemplates.xaml"/>
<ResourceDictionary Source="pack://application:,,,/UILib;component/Resources/FontResources.xaml"/>
<ResourceDictionary Source="pack://application:,,,/UILib;component/Resources/UILibResources.xaml"/>
<ResourceDictionary Source="/Views/Drawing/Terrain/Resources/CityResources.xaml"/>
<ResourceDictionary Source="/Resources/MapEditorResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Unload your csproj ( right click in solution explorer), edit it and find the node for that resource dictionary.
Change it to:
<Page Include="Properties\DesignTimeResources.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<ContainsDesignTimeResources>true</ContainsDesignTimeResources>
</Page>
Reload the project, close and re-open visual studio.
Your styles should now apply.

How to extend the number of the brushes?

I want to extend the number of colors in the System.Windows.Media.Brushes class, so I can do binding with the string name of the new Brush.
Like: value="myRed".
I use C#, .NET 4.5.2, VS2015, Windows 7.
This is not possible because the System.Drawing.Brushes class is sealed. This means it cannot be inherited from and therefore cannot be extended.
You are much better off creating a Resource Dictionary which contains your colours:
<ResourceDictionary ... >
<!-- Declare your colours here. -->
<SolidColorBrush x:Key="MyColour">#ffffff</SolidColorBrush>
</ResourceDictionary>
And then include that dictionary in your App.xaml:
<Application ... >
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- You may need to include more than one resource dictionary. -->
<ResourceDictionary Source="pack://application:,,,/Your.Project;component/Path/To/Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
You can get to those resources in the code-behind like this:
Brush myColour = (Brush)Application.Current.FindResource("MyColour");
In my opinion this is a much better way that extending the existing Brushes class because there's a clear divide between what is your code, and what is the .NET code. Not only that, having your colours in a resource dictionary promotes reuse across projects and the resources can be easily extended and become more adaptive to changing requirements.
You can find out more about resource dictionaries in the documentation.

Referencing external xaml resources dictionary file

I have a project with several classes (It's a dll project). I added a xaml file (let's call it styles.xaml) in which I declared my most commonly in-use styles.
I have another project (let's call in prog), in a different solution, in which I would like to use the styles written in styles.xaml.
I tried right clicking prog --> add existing item, and I selected the styles.xaml, wrote all the relevant code, and it worked.
The problem is that it copied the styles.xaml file to my prog project's directory (hence I'm now holding two copies of the same resource file). Unlike regular dlls refrencing, it will always look for it in that directory, and not copy it again if it doesn't exist.
In terms of source control, I don't want to save many copies of the same resource file, one for each application, and in the current solution it appears like I must.
I also tried to add resource, and select that file - same issue.
Is there anyway of doing that?
for example you have in the styles.dll:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="BlueColor" Color="Blue"/>
<!-- Whatever Styles you need -->
</ResourceDictionary>
in a BlueTheme.xaml
then reference it with:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://siteoforigin:,,,/styles;component/BlueTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Categories

Resources