I have a custom controls library, in which I defined a control template, that uses some custom styles. My control template is located in the Generic.xaml file, and the styles it uses are also located there, and accessed by the control template with the StaticResource markup extension.
In some cases, when I use this controls library, I want to change some of the styles used template, but I don't know how to do that.
I thought that if I would add to my Window's resource dictionary a style with a name, that is used by the template, my style will "override" the one that is defined in Generic.xaml file, but it didn't work.
What should I do?
does that work?
<Style TargetType="{x:Type YourCustomControl}"
BasedOn="{StaticResource {x:Type YourCustomControl}}">
<Setter Property="SomeStylePropertyOfYourCustomControl"
Value="{StaticResource SomeStyleYouWantToUseInstead}"/>
</Style>
Related
I have a WPF application using MahApps Metro for it's UI theming. I also need to use style triggers so I can appropriately determine whether a control is visible based on a property. The triggers work, but have the side effect of removing the theme. So now it looks like a default WPF unthemed CheckBox. Is there any way to preserve the MahApps Metro theme on the CheckBox?
When you assign a style, you overwrite the default style or any style applied before. If you want to extend a style, you have specify the base style using the BasedOn property.
Styles can be based on other styles through this property. When you use this property, the new style will inherit the values of the original style that are not explicitly redefined in the new style.
Specify the control type to base your style on the implicit style of the control.
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource {x:Type CheckBox}}">
<!-- ...your setters and triggers. -->
</Style>
Specify the key of the style that you want to base your style on.
<Style TargetType="{x:Type CheckBox}" BasedOn="{StaticResource MyCheckBoxBaseStyle}">
<!-- ...your setters and triggers. -->
</Style>
The named styles for CheckBox in MahApps can be found here on GitHub.
Please be aware that although your Visibility triggers should work, other triggers that are already defined in the control template of the CheckBox styles take precedence and you will not be able to redefine them in your own style. If you ever hit that case, you have to copy the corresponding style from GitHub into your project and adapt it to your requirements.
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
Is there any way to create "global" styles for all TextBoxes used in application? So I don't have to do Template=... on each TextBox ?
Yes. You need to use an implicit style.
Declare the style as normal:
<Style x:Key="MyDefaultStyle" TargetType="TextBox">
....
</Style>
Then declare:
<Style TargetType="TextBox" BasedOn="MyDefaultStyle />
The important part is that you are missing the x:Key declaration. This will get applied to all TextBoxes in your application that don't explicitly set a Style. Include this in a global resource file.
There's more information on SilverlightShow.net.
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).
Is there a way to setup global styles for my WPF application?
What I'm hoping to do is apply a style to all my Buttons that also have an Image child.
Well, sort of - it's a catch-all approach you can do - put the following element in your App.xaml - all your buttons will change (except the ones you apply a style to, manually).
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="LightPink"/> <!-- You should notice that one... -->
</Style>
However, if you want to hit only buttons with images - you have to inherit from Button everytime you do and then apply a style like this:
public class CustomImageButton:Button{}
<Style TargetType="{x:Type local:CustomImageButton}">
<Setter Property="Background" Value="LimeGreen"/>
</Style>
<local:CustomImageButton Content="ClickMe"/>
It is a very coarse-grained global styling - and you need to follow the convention to make it work.
An alternative is to use Themes - read more about that here.
You can do implicit styles in WPF which are applied by type
for instance
<Style TargetType="Button">
Will be applied to ALL the buttons within the scope of that style (If the style is in App.XAML it will apply to all buttons, if it is lower in the chain it will apply to all buttons underneath it)
If you want to apply it to only certain types of buttons (say imagebuttons) create a type that derives from button (call it ImageButton) and then create a style targeted to that type.
Put the style into a ResourceDictionary tag inside your App.xaml and it will apply to the entire app.