Apply a style to multiple controls without using a key - wpf

In .NET WPF, I have the following XAML code:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="5" />
</Style>
</StackPanel.Resources>
<CheckBox>Check 1</CheckBox>
<TextBox>Some text...</TextBox>
</StackPanel>
The controls do not have any margins applied to them.
Is it possible to apply a style to multiple controls (of different types) without using a key to set the style explicitly on each control?

Styles are not inherited, you can base the subclasses' styles on that one though using BasedOn.
Another method in this case should be using an ItemsControl with an ItemContainerStyle set to this style.
There are examples for both methods in this answer.

Sorry, I misread the question before I wrote this out. My answer is useful if you want to style multiple checkboxes within the StackPanel.
Implicitly style the entire application by placing this into your app.xaml's merged dictionaries.
<Style TargetType="CheckBox" BasedOn="{DynamicResource YourBaseStyle}"/>
This also works on a much smaller scope. Reducing the scope to just that StackPanel simply requires that you add that same line of code to your StackPanel.Resources tag.

Related

Replace Foreground color of all controls

To switch to dark theme I am currently switching merged dictionaries. DarkTheme.xaml contains:
<SolidColorBrush x:Key="GlobalTextColor" Color="#FFFFFF" />
<SolidColorBrush x:Key="GlobalBackColor" Color="#000000" />
and then each control template has something like
Foreground="{DynamicResource GlobalTextColor}"
Is there a more elegant way to replace all text at once like High Contrast theme does (without other style changes of that theme) or promised performance penalty of DynamicResource bindings?
Something like this?
<Style x:Key="Highlight" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Red"/>
</Style>
This would set all the foregrounds on each control to red.
This way you can reference it as a static resource.
Source: Can you define multiple TargetTypes for one XAML style?
Or another link here: How to target all controls (WPF Styles)
You can right click on the project from the solution explorer(in visual studio) and select open in blend.Then apply the style the needed parts and you can save it there.You can open another page or and add those styles or you can add it to the same page attributes just selecting the attribute and giving it the saved style.

Is there any way to make Style apply to all items without having to declare property

I have created a custom style for DataGrid. There are several datagrids in my application, and I would like for this style to apply to all of them.
One way of doing this is to add Style="{StaticResource DataGridDefaultStyle}" to all DataGrids.
But there must be an other way of doing this, similar to adding a theme, where I would declare style, and it would automatically apply to all DataGrids.
How do I do this?
You can use the implicit style as other have stated, but put it in your App.Xaml file's Application.Resources section, this will allow the style to be applied to all DataGrids in your application.
<Application.Resources>
<Style TargetType="DataGrid">
<Setter Property="Background" Value="LightBlue" />
</Style>
</Application.Resources>
check this Using CSS Selectors for Styling in WPF
You could try using an implicit style.
To create an implicit style, you must not include a key for the style and specify the TargetType. If you do so, the style will automatically be applied to each style of the specified type.
For example, this code will be automatically applied to all DataGrid elements:
<Style TargetType="DataGrid">
<!-- style information goes here -->
</Style>

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).

WPF - Global 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.

How to use MultiDataTrigger to check a single condition to be true in Style.Triggers in WPF?

I have three grids in my UserControl of which one control is shown at time. In the last column I need to use a Style where I need to check the data and apply a ForeGround color. I can write style at each of the control in 3 grids using DataTriggers. But I want a concrete style in Resource which can be used anywhere. I tried MultiDataTrigger but it doesn't serve my purpose as it checks 2 or more Condintions to be true in MultiDataTrigger.Conditions whereas i need to check data in a single control. Are there any alternate solution to achieve this?
If you're using some kind of a grid, you're probably using CellTemplate or some other property like that to accomplish your task. I think you do need to use different styles in different columns.
But if those styles are the same except for the triggers, then you can make one style with everything that's common to both of them, and then create another style based on the first one. It's a bit similar to inheritance in OOP.
This is how it may look like:
<Style x:Key="BaseStyle" TargetType=".....">
<!-- Common setters and triggers -->
<Setter ... />
<Setter ... />
<Setter ... />
</Style>
<Style x:Key="InheritedStyle" BasedOn="{StaticResource BaseStyle}" TargetType=".....">
<!-- This style's specific setters and triggers -->
<Setter ... />
<Style.Triggers>
...
<Style.Triggers>
</Style>

Resources