Can't apply WPF theme on the window itself - wpf

I'm trying to apply the ExpressionDark theme from the Windows Presentation Foundation (WPF) CodePlex project.
I have added the file ExpressionDark.xaml in a Themes subfolder, and changed my App.xaml file to reference this file :
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="Themes/ExpressionDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
When I run the program, the styles are applied to all controls but not the window itself. The window's background remains white. What I understand is that the style applies to Window class, but not to derived class.
To workaround this issue, I've try to create a new style in my app.xaml file, in order to inherits the Windows style for my custom window class :
<Application.Resources>
<ResourceDictionary>
<Style
TargetType="{x:Type local:MainWindow}"
BasedOn="{StaticResource {x:Type Window}}" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="Themes/ExpressionDark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The result is strictly identical.
I've also try the advise from WPF: Adventures in Theming (Part 2). I added to my window definition :
<Window
x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MyProject.ViewModel"
Title="MainWindow"
Height="350"
Width="525"
Style="{DynamicResource {x:Type Window}}" />
No more success.
What is missing?
PS: don't know if it matters, but my window's child is a Grid.

Specify Background using dynamic resource in the Window XAML
<Window x:Class="HellowWorld.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Hellow World" Height="614" Width="821"
Background="{DynamicResource WindowBackgroundBrush}">

The last time i checked there was no Window style in the theme.

Related

WPF Custom-Control Style Not Implemented

I hope someone can help me please.
I am taking my first tentative steps into WPF by first making a simple custom control. The structure is indicated below.
And the respective code is
MainWindow.xaml
<Window x:Class="WPFCustomControl.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:WPFCustomControl.NewFolder1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel Grid.Row="1">
<local:MyCustomControl x:Name = "customControl"
Content = "Click Me" Width = "70"
Margin = "10" Click = "customControl_Click"/>
<TextBlock Name = "txtBlock"
Width = "250" Height = "30"/>
</StackPanel>
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFCustomControl.NewFolder1">
<Style TargetType="{x:Type local:MyCustomControl}" BasedOn = "{StaticResource {x:Type Button}}">
<Setter Property = "Background" Value = "LightSalmon" />
<Setter Property = "Foreground" Value = "Blue"/>
</Style>
Everything works as expected.
My issue is when I move the Themes folder into the NewFolder1 the application compiles but no Style is implemented.
Thank you in advance for any advice on how to resolve this.
My issue is when I move the Themes folder into the NewFolder1 the application compiles but no Style is implemented.
That's expected. The default style for the control should be located in themes/generic.xaml. This is by convention and where the framework will look for it.
You may move your Style to another ResourceDictionary in NewFolder1 and then modify themes/generic.xaml to merge this one:
<ResourceDictionary
..>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControl;component/NewFolder1/YourDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
Or you could just define your custom Style directly in themes/generic.xaml.
Most probably you are doing following mistake,
go to App.xaml and add Styles as below example
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="NewFolder1/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

WPF apply a theme to a particular project not the entire app

I created a theme in my project1 and referenced the theme.xaml in the app.xaml. the effect is the all projects gets the same theme within the solution.
What is the simplest way to apply a theme.xaml to a specified project, i.e. only to project1 but not project2?
I know I can reference the theme.xaml in each WFP form within project1 using
<Window.Resources>
<ResourceDictionary Source="/Project1;component/Themes/Customized.xaml" />
</Window.Resources>
But that is a little bit hard to maintain if I want to change the theme for the project. What I am looking for is something like project.xaml that behave like app.xaml, only the scope is to the current project. that way I can reference the theme.xaml in one place for the specified project (but not other projects).
Is that possible?
Thanks in advance.
Create a project theme resource dictionary and put reference to FooTheme.xaml into it.
In all your windows of the project, put reference to ProjectTheme.xaml.
This way, in order to change the theme of the project, you'll need to modify only one line.
Code:
FooTheme.xaml (sample theme)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="Background" Value="Blue"/>
</Style>
</ResourceDictionary>
ProjectTheme.xaml (project theme)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<!-- In order to modify the project's theme, change this line -->
<ResourceDictionary Source="FooTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
MainWindow.xaml (sample project window)
<Window x:Class="So17372811ProjectTheme.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>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ProjectTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Content="Click me!"/>
</Grid>
</Window>

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?

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>

How to apply theme in component designer just like that in application project designer implicitly?

Say i had a theme file Button.xaml for standard button.
By merged in application resource dictionary it can implicitly applied in application project designer.
But after i move Button.xaml to component project, the component project designer can not implicitly apply the theme file.
How can i make that theme file works implicitly in component project ?
Update:
the Themes.xaml as follow
<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:,,,/StyleLibrary;component/Themes/Shared.xaml" />
<ResourceDictionary Source="pack://application:,,,/StyleLibrary;component/Themes/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/StyleLibrary;component/Themes/ComboBox.xaml" />
...
<Application x:Class="ButtonStyleTest.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="pack://application:,,,/StyleLibrary;component/Themes.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
If i use merged Theme.xaml, the Button look normal in designer, but failed in runtime.
But if i merge Button.xaml, ComboBox one by one, it look normal for both design and runtime.
New example.
Say that you have a Library called StyleLibrary.
In this Library you have a ResourceDictionary called Button.xaml which looks like this
<ResourceDictionary 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="Width" Value="75" />
<Setter Property="Height" Value="23" />
</Style>
</ResourceDictionary>
In the Application we then add a reference to StyleLibrary and in App.xaml we add this.
<Application x:Class="ButtonStyleTest.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="pack://application:,,,/StyleLibrary;component/Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
This style will apply in the Application and in the Libraries both in runtime and in designer.
To the left is my MainWindow. Is has one Button of its own, and then a UserControl from TestLibrary that has two Buttons. To the right is a Window from TestLibrary which contains one UserControl from TestLibrary, all Buttons seem to have the style applied.

Resources