I am setting a style for the Window in the App.xaml like such:
<Application x:Class="MusicRepo_Importer.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" StartupUri="TestMaster.xaml">
<Application.Resources>
<Style TargetType="Window">
<Setter Property="WindowStyle" Value="None"></Setter>
</Style>
</Application.Resources>
</Application>
With which I basically want every Window to have its WindowStyle's property value set to None (to remove the default windows frame and border); But it is not working.
What am I missing here?
I believe you have to name the style and apply it to each window like the following..
In app.xaml/resources..
<Style x:Key="MyWindowStyle" TargetType="Window">
<Setter Property="WindowStyle" Value="None"></Setter>
</Style>
Then in the window.xaml..
<Window x:Class="MusicRepo_Importer.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MyStyledWindow" Style="{StaticResource MyWindowStyle}">
This should work, but simply applying the style with TargetType for Window in the resource won't force the Window to use that style although it seems to work for other elements.
Edit:
Found some info in relation to applying default styles to a window element..
If you supply a TargetType, all
instances of that type will have the
style applied. However derived types
will not... it seems. <Style
TargetType="{x:Type Window}"> will not
work for all your custom
derivations/windows. <Style
TargetType="{x:Type local:MyWindow}">
will apply to only MyWindow. So the
options are
Use a Keyed Style that you specify as
the Style property of every window you
want to apply the style. The designer
will show the styled window.
From the Question: How to set default WPF Window Style in app.xaml?
The person who answered the question had a interesting idea about inheriting from a base window that has the style applied.
I know this question is quite old but I will answer anyway.
Here is the code that works fine for me in C# 4.0.
It just duplicates style for all subclasses in the resource dictionary.
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
if (this.Resources.Contains(typeof(Window)))
{
var types = Assembly.GetEntryAssembly().GetTypes();
var subTypes = types.Where(x => x.IsSubclassOf(typeof(Window)));
Style elementStyle = (Style)this.Resources[typeof(Window)];
foreach (Type subType in subTypes)
{
if (!this.Resources.Contains(subType))
{
this.Resources.Add(subType, elementStyle);
}
}
}
base.OnStartup(e);
}
}
Now your style from App.xaml should work for all windows.
p.s. Yeah, I know this is not the cleanest or fastest way but it works. :)
Related
I have a user control that is displayed in a popup dialog using Prism's PopupWindowAction. I don't want the window to be resizeable. Is it possible to style this window from the user control? I attempted to use this:
<UserControl.Resources>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="ResizeMode" Value="NoResize" />
</Style>
</UserControl.Resources>
but it is not working.
Edit:
Based on the accepted answer, I moved the style over to the user control that is defining the IteractionRequestTrigger and assigning the PopupWindowAction's WindowStyle.
New code in calling use control:
Add Resource
<UserControl.Resources>
<Style x:Key="WindowStyle" TargetType="Window">
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
</Style>
</UserControl.Resources>
Popup Window declaration
<prism:InteractionRequestTrigger SourceObject="{Binding InteractionRequest}">
<prism:PopupWindowAction WindowStyle="{StaticResource WindowStyle}">
<prism:PopupWindowAction.WindowContent>
<sharedV:InformationDialog />
</prism:PopupWindowAction.WindowContent>
</prism:PopupWindowAction>
</prism:InteractionRequestTrigger>
The reason why your XAML doesn't work is:
The style you created is explicit - it has a x:Key. Explicit styles have to be applied on the target element directly <Window Style="{StaticResource WindowStyle}" ... />
Even if you remove the x:Key and make it an implicit style, since it is defined in the UserControl's resources, it will only apply to items below the UserControl in the tree.
In this case you might want to look at the WindowStyle property of the PopupWindowAction. You should be able to set the style there.
Children cannot directly change their parent's style since the visual tree model is designed to go from broad to specific (Window to UserControl...) with styles being inherited and overridden in that direction. That said, anything is possible because it's all just code!
This isn't a nice way to do it, but you can use the Loaded method of your UserControl in the code behind to do the work of navigating the visual tree to find the parent Window and forcibly set the ResizeMode property. You can do this using this.Parent and checking for when is Window is true, or you can use VisualTreeHelper.GetParent.
XAML:
<UserControl Loaded="OnLoaded"></UserControl>
C#:
private void OnLoaded(object sender, RoutedEventArgs e)
{
var currentParent = Parent;
while (currentParent != null && !(currentParent is Window))
{
currentParent = VisualTreeHelper.GetParent(currentParent);
}
if (currentParent is Window parentWindow)
{
parentWindow.ResizeMode = ResizeMode.NoResize;
}
}
I was looking at this question and noticed that placing an implicit TextBlock style in Application.Resources applies that style to all TextBlocks, even those inside other controls such as Buttons, ComboBoxes, etc
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Application.Resources>
Placing the implicit style in Window.Resources does not cross control template boundaries, so things like Buttons and ComboBoxes maintain their default black text.
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Blue" />
</Style>
</Window.Resources>
Furthermore, adding the default style in the Application.Resources makes it so you can't overwrite that style with another implicit style.
<!-- Doesn't work if implicit style with same property is in Application.Resources -->
<ComboBox.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
</Style>
</ComboBox.Resources>
My questions are:
Why is this?
Are there other differences between Application.Resources and Windows.Resources?
When should use one over the other?
I understand that Application.Resources apply to the entire application, while Window.Resources apply to the window only, however I want to know why the styles in Application are treated differently than styles in Window
This is really the only special handling added to WPF and it was done by design. The code that implements it can be found in FrameworkElement, in the method FindImplicitStyleResource, which effectively does:
internal static object FindImplicitStyleResource(FrameworkElement fe, object resourceKey, out object source)
{
// ...
DependencyObject boundaryElement = null;
if (!(fe is Control))
boundaryElement = fe.TemplatedParent;
// ...
}
So the rule of thumb is that implicit Styles are always applied to controls (i.e. derives from Control). Assuming the implicit Style can be found.
For elements used in a ControlTemplate that do not derive from Control, such as TextBlock, the implicit Style look up will not cross it's templated parent. In your case above, this would be the ComboBox.
I believe this was done so that non-application implicit Styles for TextBlock were not inadvertently applied to TextBlock elements used in control templates, which the developer may or may not have known were there. The implicit Styles would only be applied to TextBlocks actually created by the developer in their own XAML.
The application implicit Styles would still allow global styling, such as increasing font size. But has probably caused more confusion than it's worth.
There is no good answer to say when to use one versus the other, as they each have their function. Obviously if you don't want to affect every TextBlock in your application, you shouldn't put the style in the application resources.
But keep in mind that this affects any non-Control element, such as Shape elements.
Pretty plain as simple
If you want Resources to be shared among the ENTIRE application you would use Application.Resources
If you want Resources to be shared among the ENTIRE Window you would use Window.Resources
If you want Resources to be shared among a single control you would use (Whatever Control).Resources
Lets say you have multiple windows but you only want a default style in one but not the other then you would use Windoe.Resources
Rachel, I don't think there is anything special to "Styles". Moreover, there isn't an issue of "crossing template boundaries". The reason for this is different and it goes to the different "Trees" in a WPF applicaiton.
By your question I recon you are picturing a world with the following hierarchy:
- Application => Window => Control => Elements within the control
There is no such hierarchy. There are different trees in a WPF applicaiton, the most famous are the Logical Tree and the Visual Tree, but there are more (the routing event tree and also the resource lookup tree, with slightly different semantics).
Assume the following XAML:
<Window x:Class="SO.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 x:Name="btn" Click="click">Click Me</Button>
</Grid>
</Window>
For this XAML, the logical tree will look like:
- Window => Grid => Button => String
The textblock inside the button is not part of the logical tree (it is part of the VisualTree though).
Looking up for resources goes by the LogicalTree, with one difference. After it reaches the top object, the finding resource algorithm will look at the Application resource dictionary, and then at the Theme resource diectionary, and then at the System resource dictionary in this order.
See following articles:
About trees: http://msdn.microsoft.com/en-us/library/ms753391.aspx
About finding resources: http://msdn.microsoft.com/en-us/library/ms750613.aspx#staticdynamic, and look for the section 'Dynamic Resource Lookup Behaviour'
Finnaly, to prove my point, add the following resource to the applicaiton XAML:
<Application x:Class="SO.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:clr="clr-namespace:System;assembly=mscorlib"
StartupUri="MainWindow.xaml">
<Application.Resources>
<clr:String x:Key="MyResource">Hello Application Resource</clr:String>
</Application.Resources>
</Application>
and the following code behind:
private void click(object sender, RoutedEventArgs e)
{
// Logical Children of btn
Debug.WriteLine("Children of btn:");
foreach( var x in LogicalTreeHelper.GetChildren(btn) ) {
Debug.WriteLine("{0} : {1}", x, x.GetType());
}
// Walk the visual tree
Debug.WriteLine("The Visual Tree:");
WalkVisual(0, this);
// Find the textblock within the button
DependencyObject p = btn;
while (p.GetType() != typeof(TextBlock))
p = VisualTreeHelper.GetChild(p, 0);
TextBlock tb = p as TextBlock;
// Now climp the textblock through the logical tree
while (p != null)
{
Debug.WriteLine("{0}", p.GetType());
p = LogicalTreeHelper.GetParent(p);
}
// Find a resource for the textbox
string s = tb.FindResource("MyResource") as string;
Debug.WriteLine("MyResource Content: {0}", s);
}
private void WalkVisual(int indent, DependencyObject p)
{
string fmt = string.Format("{{0,{0}}}{{1}}", indent * 4);
Debug.WriteLine(fmt, "", p.GetType());
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(p); ++i)
{
WalkVisual(indent+1,VisualTreeHelper.GetChild(p, i));
}
}
So ... once you understand the first question ('why is that'), the other questions fall apart. The different between application resources and window resources is that application resources can be fount by any DependencyObject in your application, including those defined in other assemblies. You'll use it when this is what you want to acheive :-)
u.
The difference lies in the scope of the styles :
when placed in Application.Resources, a style will apply to all controls in the application
when placed inside Windows.Resources, a style will apply to all controls in the window
the difference is quite subtle there, but what it means is that whatever control we're talking about (included one that's in another control's template) will get the style from application.Resources. but only the controls directly children of the window will get the style from window.Resources. A control inside antoher control's template will not have the style defined in Window.Resources since it is not directly in the window, whereas it will have the style defined in Application.Resources since it is in the application.
as for your second point, it has to do with dependency property precedence I think:
http://msdn.microsoft.com/en-us/library/ms743230.aspx
CodeNaked Answered true. It is made by WPF design. I opened the ticket question here which is a full explanation that it is by design. Also, what are online documents (dependency-property-precedence-list), function
(DependencyPropertyHelper.GetValueSource) and desktop tools (snoopwpf) to use to help you navigate through these behaviors.
While we are unhappy as WPF users (we expect the same behavior) we can't do anything about it. Options: Explicitly define content like <Label.Content> or quotation " to do considerably more work - custom templates, custom type for the content, new control etc. which I don't see as really necessary."
I am trying to modify the wpf tray icon at http://www.hardcodet.net/projects/wpf-notifyicon
the aim is to have a separate xaml file that would define a trayicon with a specific configuration, so that this configuration, in a separate file, could be easily added to say a wpf window.
im very new to wpf, but am trying to use ControlTemplate in a ResourceDictionary to achieve the aim:
Pointing to resource in App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="trayicon.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The separated configuration of trayicon.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="clr-namespace:Hardcodet.Wpf.TaskbarNotification">
<ControlTemplate x:Key="TrayIcon" TargetType="{x:Type tb:TaskbarIcon}">
<tb:TaskbarIcon x:Name="MyNotifyIcon"
IconSource="/TaskbarNotification/DefaultTrayIcon.ico"
ToolTipText="I am notified yes!"
MenuActivation="LeftOrRightClick"></tb:TaskbarIcon>
</ControlTemplate>
</ResourceDictionary>
Trying to use the configuration
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="clr-namespace:Hardcodet.Wpf.TaskbarNotification"
Title="MainWindow" Height="350" Width="525">
<Grid>
<tb:TaskbarIcon Template="{StaticResource TrayIcon}"></tb:TaskbarIcon>
</Grid>
</Window>
Exception thrown in MainWindow.xaml
The property 'Template' was not found in type 'TaskbarIcon'
My guess is that i have to add some code to this custom wpf control that woudl expose the Template property and set it how it should be set?
But i have no idea how i would do that, could you point me in the right direction please?
Wild partial guess of code needed
public static readonly DependencyProperty TemplateProperty =
DependencyProperty.Register("Template",
typeof (SomeTemplateType),
typeof (TaskbarIcon),
new FrameworkPropertyMetadata(SomeTemplateType.Empty, TemplatePropertyChanged));
[Category(CategoryName)]
[Description("Enables Templating.")]
public SomeTemplateType Template
{
get { return (SomeTemplateType)TemplateProperty; }
set { SetValue(TemplateProperty,value); }
}
Cel I dont understand the template in the first place. The control template is targetted for tb:TaskbarIcon which actually has another tb:TaskbarIcon inside it!!!
I assume you want following properties to be applied to TrayIcons across your application with their specified values...
IconSource="/TaskbarNotification/DefaultTrayIcon.ico";
ToolTipText="I am notified yes!";
MenuActivation="LeftOrRightClick"
If thats so then assuming that above properties are dependency properties, instead of creating a control template why dont you create a style which is targetted to tb:TaskbarIcon and specify Setters which set the above properties with their corresponding values.
<Style x:Name="MyNotifyIcon" TargetType="{x:Type tb:TaskbarIcon}">
<Setter Property="IconSource" Value="/TaskbarNotification/DefaultTrayIcon.ico"/>
<Setter Property="ToolTipText" Value="I am notified yes!" />
<Setter Property="MenuActivation" Value="LeftOrRightClick" />
</Style>
Then apply this style to your TaskbarIcon
<tb:TaskbarIcon Style="{StaticResource MyNotifyIcon}"></tb:TaskbarIcon>
So basically if this is what you are looking for, then template is out of question.
Please suggest if this helps you.
I am currently working on a user control that has white text and a transparent background. Unfortunately because the XAML design view within VS2010 has a white background I cannot see anything that I am designing!
I have been through all the settings dialogs I can think of, but have been unable to find a setting that changes the background colour of the XAML designer.
Does anyone know how this can be done?
Alternatively, as of VS 2013, you can do this in Tools -> Options -> Fonts and Colors, XAML UI Designer.
The editable foreground / background colors there are the colors of the checkerboard background. I just set them both to a darkish grey color that seems to work for both light and dark theme'd background stuff.
In your XAML, set your background to black. Then in your user control, use the DesignerProperties to set the background at runtime:
XAML
<UserControl .... Background="Black" .... >
Code Behind
public YourUserControl()
{
InitializeComponent();
if( !System.ComponentModel.DesignerProperties.GetIsInDesignMode( this ) )
{
this.Background = Brushes.Transparent;
}
}
Alternate Method
UserControl:
In your user control, do not declare a background color:
<UserControl ... namespaces ...>
UserControl Code Behind:
In your user control's constructor, use the DesignTime method as above, but check to see if it is Design Mode (opposite check from other method):
public YourUserControl()
{
InitializeComponent();
if( System.ComponentModel.DesignerProperties.GetIsInDesignMode( this ) )
{
this.Background = Brushes.Black;
}
}
App.xaml:
Finally, in your App.xaml, add a style to set a background color for UserControls:
<Application.Resources>
<Style TargetType="{x:Type UserControl}">
<Setter Property="Background" Value="Black" />
</Style>
</Application.Resources>
Here's what's happening:
The App.xaml will effect the UserControl at design time because a typed style is applied on an object automatically, but it is not applied to a derived object (UserControl in this case). So, at design time, VS thinks it should apply the style, but at runtime, it will be ignored.
The GetIsInDesignMode check will effect the UserControl when viewing the control in a Window that is using the UserControl because VS is compiling the UserControl at design time in order to render it in the Visual Designer.
HTH's
As shown in this post, you can condense the code to a single style by using a trigger, since DesignerProperties.IsInDesignMode is an attached property.
Actually, the code there isn't quite right. It defines an implicit style for TargetType="{x:Type UserControl}", which would be ignored at runtime anyway because your UserControl is actually a derived class -- as Metro Smurf points out in his first point:
The App.xaml will effect the UserControl at design time because a
typed style is applied on an object automatically, but it is not
applied to a derived object (UserControl in this case). So, at design
time, VS thinks it should apply the style, but at runtime, it will be
ignored.
The right way to do it would be to give it a key and apply it manually to your UserControls:
<Application
...
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=PresentationFramework">
...
<Application.Resources>
...
<Style x:Key="DesignerBlackBackgroundStyle" TargetType="Control">
<Style.Triggers>
<Trigger Property="componentModel:DesignerProperties.IsInDesignMode"
Value="True">
<Setter Property="Background" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
and:
<UserControl x:Class="MyUserControl"
Style="{StaticResource ResourceKey=DesignerBlackBackgroundStyle}">
As a trigger, this has an extra benefit over setting the background in code-behind -- it will behave properly if the background is explicitly set somewhere else, such as from a containing UserControl:
<UserControl x:Class="ContainerUserControl" ...>
...
<local:MyUserControl Background="Gray" />
Local values have precedence over style triggers, so on this screen the designer would use a gray background, whereas it would be black when designing MyUserControl stand-alone.
Are you able to use Blend for designing? Blend has an option to switch between light and dark color schemes.
Set the background color of the usercontrol to black in the XAML, then set it to transparent in code.
Edit:
If you're not comfortable leaving the code this way, then you can revert this change before you release, once you are done with all the designer work, though there is no harm in leaving it in.
Set the XAML Designer background color to Gray.
Tools > Options> Fonts and Colors:
Show settings for: XAML Designer,
Display items: Artboard Background,
Item foreground/background: Gray.
Now you can see text in XAML Designer
It's a shame there is this inconvenience.
I am trying to set the default Style for every window in my WPF Windows application in my app.xaml. So far i have this in app.xaml:
<Application.Resources>
<ResourceDictionary>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="Background" Value="Blue" />
</Style>
</ResourceDictionary>
</Application.Resources>
I can get the window to appear with this style when running the app (but not in VS designer) by specifically telling the window to use this style via:
Style="{DynamicResource WindowStyle}
This works, but is not ideal. So how do I:
Have all windows automatically use the style (so i don't have to specify it on every window)?
Have VS designer show the style?
Thanks!
To add on to what Ray says:
For the Styles, you either need to supply a Key/ID or specify a TargetType.
If a FrameworkElement does not have an
explicitly specified Style, it will
always look for a Style resource,
using its own type as the key
- Programming WPF (Sells, Griffith)
If you supply a TargetType, all instances of that type will have the style applied. However derived types will not... it seems. <Style TargetType="{x:Type Window}"> will not work for all your custom derivations/windows. <Style TargetType="{x:Type local:MyWindow}"> will apply to only MyWindow. So the options are
Use a Keyed Style that you specify as the Style property of every window you want to apply the style. The designer will show the styled window.
.
<Application.Resources>
<Style x:Key="MyWindowStyle">
<Setter Property="Control.Background" Value="PaleGreen"/>
<Setter Property="Window.Title" Value="Styled Window"/>
</Style>
</Application.Resources> ...
<Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}"> ...
Or you could derive from a custom BaseWindow class (which has its own quirks), where you set the Style property during the Ctor/Initialization/Load stage once. All Derivations would then automatically have the style applied. But the designer won't take notice of your style You need to run your app to see the style being applied.. I'm guessing the designer just runs InitializeComponent (which is auto/designer generated code) so XAML is applied but not custom code-behind.
So I'd say explicitly specified styles are the least work. You can anyways change aspects of the Style centrally.
Know this is years later, but since the question is still up here...
Create a resource dictionary in your project (Right-click the project...)
I'll create a new folder under the Project called "Assets" and
put "resourceDict.XAML in it.
Add the code to resourceDict.XAML:
<Style x:Key="WindowStyle" Target Type="Window" >
<Setter Property="Background" Value="Blue" />
</Style>
In your Project XAML file add the following under Window:
<Window.Resources>
<ResourceDictionary>
<!-- Believe it or not the next line fixes a bug MS acknowledges -->
<Style TargetType="{x:Type Rectangle}" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Assets/resourceDict.XAML" />
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
</Window.Resources>
ref the following web site: Trouble referencing a Resource Dictionary that contains a Merged Dictionary
"There is a bug: if all your default styles are nested in merged dictionaries three levels deep (or deeper) the top dictionary does not get flagged so the search skips it. The work around is to put a default Style to something, anything, in the root Dictionary."
And it seems to fix things reliably. Go figure...
And finally, under Window, maybe after Title, but before the final Window '>' :
Style="{DynamicResource windowStyle}"
And you'll need to add the code in steps 3 & 4 to every project to which you want the style to apply.
If you wanted to use a gradient background rather than a solid color, add the following code to the resourceDict.XAML:
<LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0"
EndPoint="0,1" >
<GradientStop Color= "AliceBlue" Offset="0" />
<GradientStop Color= "Blue" Offset=".75" />
</LinearGradientBrush>
And modify your Style Setter for the background color to read:
<Setter Property="Background" Value="{DynamicResource
windowGradientBackground}" />
Steps 3 & 4 need to be repeated in each project.XAML file as described above, but hey, you get uniform Windows across the Solution! And the same process could apply to any controls you want to have a uniform look as well, buttons, whatever.
For anyone coming into this late, hope this helps as I'm sure the original posters got this all figured out years ago.
Paul
The designer is not working because you're specifying a DynamicResource. Please change this to StaticResource and all will be well.
To apply to all windows, you should remove the x:Key from the style. Setting the TargetType implicitly sets the x:Key to whatever is in TargetType. However, in my tests, this is not working, so I am looking into it.
If I set the TargetType to x:Type TextBlock, the designer works perfectly, it just seems to be the Window that is showing different behaviour.
You can add this code to your App.xaml.cs file:
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
{
DefaultValue = Application.Current.FindResource(typeof(Window))
});
After this, the style applied to the Window type will also apply to all types derived from Window
I investigated this one for some days now and made it work through the Constructor of my custom Window Class:
public class KWindow : Window
{
public KWindow()
{
this.SetResourceReference(StyleProperty, typeof(KWindow));
}
static KWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// gets called finally
}
}
Hope it helps someone
For those this struggling with a solution to the problem: How can I have a custom style be automtically applied to all my Window derived types? Below is the solution I came up with
NOTE: I really didn't want to derive from the Window type or have to insert XAML on each window to force a style update etc. for reasons specific to my project (consumers of my product us my generic reusable style library and create their own layout/windows etc.) so I was really motivated to figure a solution out that worked that I was willing to live with any side effects
Need to iterate through all the instantiated windows and simply force them to use the new custom style you have defined for the Window type. This works great for windows that are already up but when a window or child window is instantiated it won't know to use the new/custom type that has been declared for its base type; the vanilla Window type. So the best I could come up with was to use the LostKeyBoardFocus on the MainWindow for when it loses Focus to a ChildWindow (IOW When a child window has been created) and then invoke this FixupWindowDerivedTypes().
If someone has a better solution for "detecting" when any kind of window derived type is instantiated and thus call the FixupWindowDerivedTypes() that would be great. There may be something useful with handling the WM_WINDOWPOSCHANGING in this area as well.
So this solution is not elegant per say but gets the job done without me having to touch any code or XAML related to my windows.
public static void FixupWindowDerivedTypes()
{
foreach (Window window in Application.Current.Windows)
{
//May look strange but kindly inform each of your window derived types to actually use the default style for the window type
window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window));
}
}
}
}
//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection.
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html
//Helper class to retrieve a protected property so we can set it
internal class DefaultStyleKeyRetriever : Control
{
/// <summary>
/// This method retrieves the default style key of a control.
/// </summary>
/// <param name="control">The control to retrieve the default style key
/// from.</param>
/// <returns>The default style key of the control.</returns>
public static object GetDefaultStyleKey(Control control)
{
return control.GetValue(Control.DefaultStyleKeyProperty);
}
}
Considering Gishu's answer I figured out one more workaround. But it could be little bit weird.
If you use MVVM pattern you could remove code-behind of your window and x:Class markup in XAML file. So you will get an instance of window or your custom window but not a some instance of 'MainWindow' class that is derived from 'Window' class and marked as partial.
I'm making VS-like window so I had to inherit window class and extend it functionality. In that case it will be possible to make new window class as partial that would allow us to make code-behind without inheritance.
you will save all the styles in one xaml file(example design.xaml)
and then call that (design.xaml) xaml file in all the pages like this way
Like:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Design.xaml"/>
</ResourceDictionary.MergedDictionaries>