A strange problem with WPF Window.Icon - wpf

I'm going to set Window.Icon property by using ResourceDictionary like below:
<Style TargetType="{x:Type Window}">
<Setter Property="Icon" Value="/WpfApplication1;component/Resources/Icon.ico" />
</Style>
Above Style wasn't change Icon of Window. However when i set Icon of Window directly, It is done correctly!
<Window Icon="/WpfApplication1;component/Resources/Icon.ico">
//Content
</Window>
Note: Build Action of Icon.ico was set to Resource and ResourceDictionary also loaded.

The problem is that your style is not applied at all. You'll have to define your style in app.xaml, assign a key to it and set your windows style explicitly.
EDIT:
Goblin suggested another valuable solution, excerpt from his comment:
he could set the TargetType="{local:MainWindow}" where local is the namespace for WPFApplication1. The problem is that 'empty key'-application works only for the specified type - not descendants.

Related

What is the Equivalent of SetResourceReference in a Metro Application?

I'm attempting to set a reference to a style in a control I'm creating in the code behind. Normally in WPF, I'd use the SetResourceReference method. However, I see that this method doesn't seem to exist on the Button property in Metro.
What is the equivalent in a Metro application?
WinRT, like Silverlight, doesn't have that technique (it's missing "DynamicResource" markup extension and the support that goes with it).
You could try one of the following:
Set the style property
Set the template property
To set the Style for example, you can do something like this.
With Resources:
<Page.Resources>
<Style TargetType="Button" x:Key="boldButton">
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Page.Resources>
and a button:
<Button Name="btn" Content="Button" />
In the code behind:
btn.Style = this.Resources["boldButton"] as Style;
I ended using a custom implementation of TryFindResource shown here. The problem with using the this.Resources property suggested in a different answer is that it doesn't search up the entire resource tree for resources that might be in the App resources. The implementation in the link I provided does that. It is based off of something common in Silverlight which has the same issue.

My custom control in ToolBar

I have a specific control. I want to make style for it when it is placed in ToolBar. I have found how to do it in case of Button, CheckBox and other standard controls, but how I should make it for my control?
<Style x:Key="MyStyleForCustomControl" TargetType="{x:Type NameSpace:CustomControl}">
// Your setter's for your controls go here.
</Style>
NameSpace - where your Control is present
CustomControl - Name of your control.
Is this what you want?
EDIT:
If you want Style for Toolbar in your control, simply place the style in your UserControl Resources, it will be applied to the Toolbar placed within your control. The scope for this style will be limited to your control and will be hidden outside your control.
<UserControl.Resources>
<Style TargetType="{x:Type ToolBar}">
....
</Style>
</UserControl.Resources>
Ok now you clarified your question I think I can give you a solution. It looks like you simply need to set the ItemContainerStyle of the ToolBar control for your specific user control. First declare the "my" namespace where your specific control is located, then just add something like this:
<ToolBar>
<ToolBar.ItemContainerStyle>
<Style TargetType="{x:Type my:MyUserControl}">
<Setter Property="Background" Value="Azure"/>
</Style>
</ToolBar.ItemContainerStyle>
<my:MyUserControl/>
</ToolBar>
If you wanna add other control types to the ToolBar like the Button you mentioned above, then you will need to define a custom StyleSelector instead that you will set to the ItemContainerStyleSelector property. Here is a pretty good sample of StyleSelector implementation: Style Selectors

WPF Grid.Resources Style breaks ResourceDictionary Style. How to make them coexist?

In a WPF app I have a ResourceDictionary with Style defined for the TargetType MyCustomControl:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:MyControlLibrary;assembly=MyControlLibrary" >
<Style TargetType="{x:Type cc:MyCustomControl}">
<Setter Property="Prop1" Value="1" />
<Setter Property="Prop2" Value="2" />
...
The problem is that I need to define a context menu for MyCustomControl in the page XAML like following:
<Grid>
<Grid.Resources>
<ContextMenu x:Key="MyControlContextMenu">
<MenuItem Name="Name1"
Header="Header1"
Click="Cm1_Click"
.../>
....
</ContextMenu>
<Style TargetType="{x:Type ScNamespace:MyCustomControl}">
<Setter Property="ContextMenu" Value="{StaticResource MyControlContextMenu}"/>
</Style>
</Grid.Resources>
...
In this case, though I only assign one Property in the Style definition inside my Grid, the ResourceDictionary Style values are not applied at all. They get overridden by page resource style and ignored.
How to solve this issue? Maybe there is a way to make a reference to ResourceDictionary in the Grid.Resources section to enforce looking up the ResourceDictionary Style?
Base your new style on your default style:
<Style TargetType="{x:Type ScNamespace:MyCustomControl}" BasedOn="{StaticResource {x:Type ScNamespace:MyCustomControl}}">
<Setter Property="ContextMenu" Value="{StaticResource MyControlContextMenu}"/>
</Style>
Not sure if it is what you're looking for, but a Style can inherit from another. With the BasedOn-property you can define the base style of a Style, so that the new style inherits all settings from this style.
However I never tried if it works also if the BasedOn references to the same key (type). Maybe it works:
<Style TargetType="{x:Type ScNamespace:MyCustomControl}"
BasedOn="{x:Type ScNamespace:MyCustomControl}">
If this works not, maybe you can separate the Style, define it globaly with a key and then reference to the globaly defined Style via the BasedOn-property.
In general, Controls should have their default Styles defined in the Themes folder in a theme specific file (see here for more info).
When an application looks for a
resource, it looks at three levels in
the following order:
1) The element level.
The system starts with the element
that references the resource and then
searches resources of the logical
parent and so forth until the root
element is reached.
2) The application level.
Resources defined by the Application
object.
3) The theme level.
Theme-level dictionaries are stored in
a subfolder named Themes. The files in
the Themes folder correspond to
themes. For example, you might have
Aero.NormalColor.xaml,
Luna.NormalColor.xaml,
Royale.NormalColor.xaml, and so on.
You can also have a file named
generic.xaml. When the system looks
for a resource at the themes level, it
first looks for it in the
theme-specific file and then looks for
it in generic.xaml.
In your case, you have two implicit Styles, so HCL and Kent's answers should work. Since only one implicit Style can be applied at a time. Same goes for setting the Style properly directly. In that case, no implicit Styles will be applied.
If you have your first Style setup as a default Style at the theme level, then it would be applied in addition to your second implicit Style (or any explicitly defined Style).

Black Background for XAML Editor

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.

How to set default WPF Window Style in app.xaml?

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>

Resources