WPF Auto-assign styles to children through parent style - c#

I got several StackPanels in my application which want their children to apply certain styles:
<StackPanel.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource SettingLabel}" />
<Style TargetType="DockPanel" BasedOn="{StaticResource SettingRow}" />
<Style TargetType="CheckBox" BasedOn="{StaticResource SettingCheckBox}" />
<Style TargetType="PasswordBox" BasedOn="{StaticResource DialogPasswordBox}" />
<Style TargetType="TextBox" BasedOn="{StaticResource DialogTextBox}" />
</StackPanel.Resources>
Instead of writing these 5 lines over and over again I though of giving the StackPanel itself a style which will apply those and therefore reduce redundancy.
It is not possible to set Resources in a style setter because it's no dependency property:
<Style x:Key="SettingPanel" TargetType="StackPanel">
<Setter Property="Resources">
<Setter.Value>
<Style TargetType="TextBlock" BasedOn="{StaticResource SettingLabel}" />
<Style TargetType="DockPanel" BasedOn="{StaticResource SettingRow}" />
<Style TargetType="CheckBox" BasedOn="{StaticResource SettingCheckBox}" />
<Style TargetType="PasswordBox" BasedOn="{StaticResource DialogPasswordBox}" />
<Style TargetType="TextBox" BasedOn="{StaticResource DialogTextBox}" />
</Setter.Value>
</Setter>
</Style>
So is there any other way to do this without having to set the styles on every child and repeat the assignment styles?

You can define styles in Style.Resources of StackPanel. These will be applied to all the children of StackPanel using SettingPanel as style.
<Style x:Key="SettingPanel" TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource SettingLabel}" />
<Style TargetType="DockPanel" BasedOn="{StaticResource SettingRow}" />
<Style TargetType="CheckBox" BasedOn="{StaticResource SettingCheckBox}" />
<Style TargetType="PasswordBox" BasedOn="{StaticResource DialogPasswordBox}" />
<Style TargetType="TextBox" BasedOn="{StaticResource DialogTextBox}" />
</Style.Resources>
</Style>

Related

ColumnHeaderStyle Not Working While adding it to DataGridStyle

I'm trying to create a new DataGridStyle as follows:
<ResourceDictionary>
<Style
x:Key="DGR"
BasedOn="{StaticResource {x:Type DataGridRow}}"
TargetType="DataGridRow">
<Setter Property="Background" Value="Yellow" />
</Style>
<Style
x:Key="DGC"
BasedOn="{StaticResource {x:Type DataGridColumnHeader}}"
TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="Blue" />
</Style>
<Style
x:Key="DataGridStyle"
BasedOn="{StaticResource {x:Type DataGrid}}"
TargetType="{x:Type DataGrid}">
<Setter Property="ColumnHeaderStyle" Value="{DynamicResource DGC}" />
<Setter Property="RowStyle" Value="{DynamicResource DGR}" />
</Style>
</ResourceDictionary>
My DataGrid is just like this:
<DataGrid Style="{DynamicResource DataGridStyle}"/>
But because of some reason only the DataGridRow style is working, the columnHeaderStyle style seems to be ignored.
If I set the ColumnHeaderStyle explicitly it works:
<DataGrid Style="{DynamicResource DataGridStyle}" ColumnHeaderStyle="{DynamicResource DGC}"/>
Here's an use example of DataGrid.ColumnHeaderStyle Property from Microsoft.
Try to put your Column Header style in your Datagrid's style resource like below, it should work then.
<Style x:Key="DataGridStyle"
BasedOn="{StaticResource {x:Type DataGrid}}"
TargetType="{x:Type DataGrid}">
<Style.Resources>
<Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}" >
<Setter Property="Background" Value="Blue" />
</Style>
</Style.Resources>
<Setter Property="RowStyle" Value="{DynamicResource DGR}" />
</Style>

How can I style only those Buttons which are in a DataGrid?

In App.xaml I have styled all my Buttons.
<Style TargetType="Button">
<Setter Property="Margin" Value="3"/>
</Style>
I realized if the Button is in a DataGrid then I not need a margin. I have a lot of DataGrid and I put this code into all of them one by one.
<DataGrid.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="0"/>
</Style>
</DataGrid.Resources>
Is there a more clever way to do this?
You can define Style for DataGrid and within that, add child control style to particular modification.
If you want to add this Style to all the DataGrids, no need to defineKey.
<Style x:Key="dataGrid" TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
Declare a style with the key in the Window.Resources or App.Resources as shown below.
<Window.Resources>
<Style TargetType="Button" x:Key="dataGridButtonStyle">
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Wheat"/>
</Style>
</Window.Resources>
Then apply the style to the control using the StaticResource with the key(in this example key name is dataGridButtonStyle)
<Button Style="{StaticResource ResourceKey= dataGridButtonStyle}" Content="Hello"/>
Please add resource file at Windows or User control level so that it will apply all child controls as below,
<Window.Resources>
<Style TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
<Window.Resources>
or
<UserControl.Resources>
<Style TargetType="DataGrid">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
<Setter Property="Margin" Value="0" />
</Style>
</Style.Resources>
</Style>
</UserControl.Resources>

2 Different ComboBox Styles with 2 Different ComboBoxItem Styles

I have 2 ComboBox-Styles in my WPF-Application. They're look both like this:
<Style TargetType="{x:Type local:MyComboBox1}">
<Style.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Style.Resources>
<Setter Property="SnapsToDevicePixels" Value="true" />
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyComboBox1}">
...
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers />
</Style>
Now I want to style the ComboBoxItems for each ComboBox in a different way. How can i do this?
You can use the ItemContainerStyle property
<Style TargetType="Combobox" x:Key="myStyleOne">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem">
<!-- put your style here -->
</Style>
</Setter.Value>
</Setter>
</Style>
And then you can use your style like the following.
<ComboBox Style="{StaticResource myStyleOne}" />

How to make style to extend but not override other styles

On the current window I have a Grid with multiple controls (labels, textboxes, buttons).
General styles are set in App.xaml. Extensions for each control are set in Grid resources.
Each control visibility is determined by viewmodel property value. Not to bind each controls visibility to it (it uses custom converter and this will cause lots duplications) I wish to have "MyVisible1" style.
The problem is if I apply this style it overlaps other properties. What value should I use in "BasedOn"? Or what else can I do to implement it?
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Control}" x:Key="MyVisible1">
<Setter Property="Visibility" Value="{Binding ...}" />
</Style>
<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Width" Value="80" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Width" Value="45" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</Grid.Resources>
<TextBox Grid.Column="0" Grid.Row="0" Style="{StaticResource MyVisible1}"/>
</Grid>
The only way that I can imagine that you can do this is to define a local implicit Style for this:
<Style TargetType="{x:Type Control}">
<Setter Property="Visibility" Value="{Binding ...}" />
</Style>
By not defining an x:Key, this Style will be implicitly applied to all controls that extend the Control class and by declaring it locally, it will only apply to those elements in the current focus scope. So defining it in a Grid.Resources section will implicitly apply it to all controls within that Grid. You are then free to apply whatever additional Styles that you want to these controls.

WPF StackPanel.Resources setter on more than one control type?

I want to use a setter to set a default margin of all elements in my stackpanel, not just buttons but also textboxes and labels.
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
</StackPanel.Resources>
...
When I try to change above Button to Control or FrameworkElement (a derived type of each element) it doesn't work.
How can I fix this without having to specify 2 different Style elements with the same content but different x:Types on the TargetType?
You can do this with inheritance via Style's BasedOn attribute:
<StackPanel.Resources>
<Style x:Key="BaseStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Margin" Value="0,10,0,0"/>
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}" />
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource BaseStyle}" />
</StackPanel.Resources>

Categories