Loading WPF Style from Resource File - wpf

I am trying to load WPF Style from other file actually from WPF Custom Control Library
but i am failing to load here is my solution.
The solution contains two projects
WpfTestControls of Type WPF Custom Control Library
WpfTestApp of type WPF Application Library which has reference to WpfTestControls
MainWindow.xaml from WPF Application Library
<Window.Resources>
<Style x:Key="TempStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<TextBox Height="50px" Width="100px" Style="{DynamicResource TempStyle}"/>
</Grid>
Generic.xaml from WPF Custom Control Library
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/WpfTestControls;component/TextBoxStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
TextBoxStyle.xaml from WPF Custom Control Library
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="TempStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Green"/>
</Style>
My AssemblyInfo.cs file contains the following
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries))]
But still i am failing to load the Style.
If i am using the not using the Generic.xaml everything work fine for example the following code works as expected
<Window x:Class="WpfTestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="TempStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Green"/>
</Style>
</Window.Resources>
<Grid>
<TextBox Height="50px" Width="100px" Style="{StaticResource TempStyle}"/>
</Grid>
What am i doing wrong ?
Thanks in advance

Please answer few things for me...
Is "WPF Custom Control Library" assembly same as "WpfTestControls" assembly?
If not, then does "WPF Custom Control Library" have a reference to the "WpfTestControls" assembly?
Does your WpfTestApp have a reference to both "WPF Custom Control Library" and "WpfTestControls" assemblies?
If you add that reference(s), the resources should load correctly.
My Steps...
Add a "WPF Custom Control Library" say "ThemesLibray"
In this add two resource dictionaries under "Themes" folder
TextBoxStyle.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="GreenTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Green"/>
</Style>
</ResourceDictionary>
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="TextBoxStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
I have main starup project "MyWPFTestApp" that has assembly reference to ThemesLibray. In that the window has ThemesLibrary resources merged this way....
<Window x:Class="MyWPFTestApp.Window7"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window7" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/ThemseLibrary;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<TextBox Style="{StaticResource GreenTextBoxStyle}"/>
</Grid>
</Window>
When I launch MyWPFTestApp, I see the Window with green TextBox.

Main thing is : Make sure you have Build Action of your Resource Dictionary set to Resource.

Related

Style Defined in app.xaml is only applied in the Designer but not a Runtime

I put the two following Style in App.xaml of my WPF application. If I change the FontSize to a different value, the Designer of Visual Studio 2019 shows all the controls with the specified FontSize. If I run the app, the controls show a FontSize of 12.
<Application x:Class="testapp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:testapp"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="View/Themes/ButtonStyle.xaml"/>
<ResourceDictionary Source="View/Themes/CheckBoxStyle.xaml"/>
<ResourceDictionary Source="View/Themes/ComboBoxStyle.xaml"/>
<ResourceDictionary Source="View/Themes/DataGridStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Page}">
<Setter Property="FontSize" Value="18" />
</Style>
<Style TargetType="{x:Type Window}">
<Setter Property="FontSize" Value="18" />
</Style>
</ResourceDictionary>
</Application.Resources>
If you research a bit, there has been an issue on this going back ten+ years on windows/pages. In design time the designer will get the style, but due to the Page/Window being derived types, during runtime they won't.
The fix (or workaround depending one one's viewpoint) is to name the style in app.xaml with x:key such as (page only shown for brevity):
<Style x:Key="pStyle" TargetType="{x:Type Page}">
<Setter Property="FontSize" Value="18" />
</Style>
and then set to the static resource style on each page/window such as below
Style="{StaticResource pStyle}"
such as:
<Page x:Class="WPFStack.ListBox.ListViewQuestion"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFStack.ListBox"
mc:Ignorable="d"
xmlns:model="clr-namespace:WPFStack.Model"
d:DesignHeight="450" d:DesignWidth="800"
Style="{StaticResource pStyle}"
Title="ListViewQuestion">
See How to set default WPF Window Style in app.xaml

Applying global styles to combobox

I'm trying to apply a global style to all ComboBoxes in my application. I'm doing this by defining a Style in my App.xaml file and specifying a TargetType, which should apply that style to all controls that are of the specified type. However, it appears that my style is not being applied at all.
Here's my code:
App.xaml
<Application x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Background" Value="Red"></Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox Margin="173,130,186,166"></ComboBox>
</Grid>
</Window>
I do not have any code-behind at this point other than the default code that VS generates for WPF forms.
I expect this XAML code to change the background of any ComboBoxes in any window to red, without me needing to manually specify the style for each ComboBox. (I really don't want write it out manually for each ComboBox - my app will end up using many, many CBs and it would be a major pain - not to mention it looks cluttered.)
I tried to model my code after this question but did not get any results.
Try to avoid the nested ResourceDictionary in the App.Xaml.
Fix in this way:
<Application.Resources>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Background" Value="Red"></Setter>
</Style>
</Application.Resources>
I would suggest to create a folder in your solution and add in it a Xaml control : ResourceDictionary where you gonna define all your global styles you want to apply by default.
For example :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="25"/>
<Setter Property="Background" Value="red"></Setter>
</Style>
</ResourceDictionary>
Now, you just need to put a reference in you App.Xaml like this :
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Views/Style/GlobalStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Hope it'll help you.
Have a good day.

Apply themes to wpf and use styles

I am trying to apply a theme to a bunch of wpf projects. There is one assembly containing the generic.xaml and different applications. As far as i understand i can't use the ThemeInfo attribute with ResourceDictionaryLocation.ExternalLocation because the name have to be the same as my program but I have more than one program...
So I search and found that I only have to include the dictionary as MergedDictionary in the app.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ClassLibrary1;component/Themes/generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
This basically works. But if I use a style for the controls it will not apply the generic.xaml style anymore:
generic.xaml in ClassLibrary1.dll
<ResourceDictionary x:Class="ClassLibrary1.Themes.generic"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Black" />
</Style>
Window in program
<Window x:Class="Theming.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="Button"
x:Key="ButtonGreenTextStyle">
<Setter Property="Foreground"
Value="Green" />
</Style>
</Window.Resources>
<Grid>
<Button Style="{DynamicResource ButtonGreenTextStyle}" Content="Test" />
</Grid>
</Window>
What I have to do, that WPF will understand the style in my generic.xaml as basestyle for all buttons (I know I will also have to write a ControlTemplate; the above code is just for simplicity)
Two things I would try
Create a generic ButtonBase style/template to set the look of all
buttons
Try using a BasedOn attribute on the ButtonGreeTextStyle,
basing it on an existing style.
I found another solution. You have to write styles based on a custom markup:
This will apply the current theme style. The code for this MarkupExtension can be found here:
How do I alter the default style of a button without WPF reverting from Aero to Classic?

ResourceDictionary fails to merge external ResourceDictionaries

I Have a ResourceDictionary Generic.xaml which consists of a set of other resource dictionaries, this is achieved by merging dicionaries. If no resources other than merged dictionaries are defined in my Generic.xaml, during the runtime no styles gets applied.
However if I define any styles in the Gerneric.xaml all starts to work properly.
So the example below doesn't work (this is from my Generic.xaml)
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources;component/ResourceDictionaries/CommonControls/CommonControlsResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!--<Style TargetType="{x:Type ToolTip}"/>-->
And here is the working version:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources;component/ResourceDictionaries/CommonControls/CommonControlsResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type ToolTip}"/>
Why is that happening?
Edit:
To pin point the problem I have created a sample solution. So the structure of the project is following:
ProjectA WPF Windows Application
ProjectC Class Library, containing styles which are share among all project in the solution folder.
Here is the ProjectA:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/ProjectC;component/Themes/ThemeZ.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!--<Style TargetType="{x:Type ToolTip}"/>-->
</ResourceDictionary>
<Application x:Class="MergedResourceDictionaryIssue.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
<Window x:Class="MergedResourceDictionaryIssue.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button/>
</Grid>
</Window>
Here is the ProjectC:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Styles for all our buttons, let make them all red squares -->
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Width="50"
Height="50"
Background="Red" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
And again if I uncomment the code in the ResourceDictionary project renders as expected, but otherwise the resource dictionary is simply ignored.
According to me, a Dictionary can only contain :
- merged dictionaries
- OR styles
Edit : They are discussing about it here It's a "known" issue and the trick that you used is the currently workaround.

Set resource or style to a window from different class library

I am following prism to build wpf application. In my application, there is a helper class library where I defined resources and styles which is going to be used by multiple class libraries in the solution.
But I am getting error when I try to set a resource to Style attribute of a window. The window is in differnt class library as of a resource.
The error that I am getting is :
Cannot find resource named '{resourceName}'. Resource names are case sensitive. Error at object 'MyWindow' in markup file
I used the following code but it is not working
<Window x:Class="Class1" Style="{StaticResource resourceName}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/classlibrary;component/Dictionary/resource1.xaml" /> </ResourceDictionary.MergedDictionaries>
< /ResourceDictionary>
< /Window.Resources>
</Window>
You need to use the DynamicResource markup extension. The reason for this is because the external ResourceDictionary you import is declared in your xaml after the style is set for your Window. A working example of setting a Window's style with a style defined in a referenced class library is below:
The "MainWindow" xaml:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Style="{DynamicResource TestStyle}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/ClassLibrary1;component/Styles.xaml">
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
</Grid>
</Window>
The ResourceDictionary (defined in a file named Styles.xaml) in a class library:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="TestStyle" TargetType="Window">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="Green"></SolidColorBrush>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
You can use a pack URL to get a resource dictionary from another assembly. Check this thread.
Here is an example of a resource dictionary read from a Common assembly:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Common;component/styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Resources