I am in the process of creating a base window class for most of my windows to derive from. Obviously the best solution for this was a separate class, and a style that applies to it.
The issue is that the <Style ../>
I have is not being applied when it is in App.Resources
. That is, if it's defined in an external ResourceDictionary
, and merged into App.xaml
's resources, or a local dictionary and merged, or placed inline into App.Resources
. The <Style ../>
is, however, applied when it is placed into Themes/Generic.xaml
.
The problem can be demonstrated without doing anything special at all in the base window, apart from overriding the DefaultStyleKeyProperty
.
Below is ThemeWindow
:
public class ThemeWindow : Window
{
static ThemeWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(typeof(ThemeWindow)));
}
}
Here is the very simple <Style ../>
I am trying to apply (it makes the Window
background red, nothing more):
<Style TargetType="{x:Type testing:ThemeWindow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type testing:ThemeWindow}">
<Grid>
<Grid.Background>
<SolidColorBrush Color="Red"/>
</Grid.Background>
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The MainWindow
that uses ThemeWindow
, is simply the following XAML:
<testing:ThemeWindow x:Class="Testing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:testing="clr-namespace:Testing"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="125,83,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</testing:ThemeWindow>
Now, as stated, if you place that Style
in its own ResourceDictionary
, and include it like this:
<App.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Themes/ThemeWindow.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</App.Resources>
.. it does not work. If you inline the style straight into App.Resources
, it does not work.
The only situation I can find it working is to call the ResourceDictionary
xaml Generic.xaml
, and place it into the Themes/
directory of the application.
I am wondering exactly why this is happening.
My only theory is that when WPF sees a control type, it will head over to Themes
, and scan all ResourceDictionary
s for the type, then fall back to Generic.xaml
and load it. This doesn't explain why it would not load if the <Style />
is available in a merged ResourceDictionary
though. Note that it does work if the MergedDictionary
is placed into Generic.xaml
, for obvious reasons.
I'm perfectly fine with having to merge the ResourceDictionary
into Generic.xaml
if that's what I have to do. I just want to get down at the technical details as to why it needs to be like this.
Screenshots of this not working / working:
Apply a style implicitly You can change the default appearance by setting properties, such as FontSize and FontFamily, on each TextBlock element directly. However, if you want your TextBlock elements to share some properties, you can create a Style in the Resources section of your XAML file, as shown here.
Window is the root window of XAML applications which provides minimize/maximize option, title bar, border, and close button. It also provides the ability to create, configure, show, and manage the lifetime of windows and dialog boxes.
I have a simple workaround that would allow you to set your Style in you app.xaml.
Define your style in app.xaml like this :
<Style x:Key="{x:Type testing:ThemeWindow}" TargetType="{x:Type testing:ThemeWindow}">
And change your ThemWindow to this :
public class ThemeWindow : Window
{
static ThemeWindow()
{
StyleProperty.OverrideMetadata(typeof(ThemeWindow), new FrameworkPropertyMetadata(GetDefautlStyle()));
}
private static Style GetDefautlStyle()
{
if (defaultStyle == null)
{
defaultStyle = Application.Current.FindResource(typeof(ThemeWindow)) as Style;
}
return defaultStyle;
}
private static Style defaultStyle = null;
}
It does not really solve the question, but that would allow you to achieve what you need !
EDIT : Looking at DefaultStyleKey reference, it's clearly stated that it's used for theme style lookup. That explains why it won't find it in app.xaml or any other dictionary. It will only search in Theme dictionaries. So you either have to define your style in a Theme Dictionary, or to use the Style property directly as in the above example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With