How to base a style on an inherited style - c#

So I have a Master Detail page. And in my Master page I have a style that will set the style for all buttons.
Master Page
<Style TargetType="Button">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="RenderTransformOrigin" Value="-0.893,-11.7"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
in my Detail Page I have a button where I would like to add some triggers to through the style
<Button Content="{Binding DeleteMultipleButton}" Margin="0,0,5,0" CommandParameter="{Binding ElementName=files, Path=SelectedItems}" Command="{Binding DeleteMultipleFiles}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Deleting}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
But this overwrites the inherited style and I lose my button styling. Is there a way I can base my button style on the inherited style? (I can't do this through static resource and a key because the resource is in a different page)

You can use the BasedOn property:
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
Keep your base button style as it is:
<Style TargetType="Button">
<Setter Property="Background" Value="White" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="RenderTransformOrigin" Value="-0.893,-11.7"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
And apply the BasedOn property to the button on the Detail Page:
<Button>
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
...
</Style>
</Button.Style>
</Button>

So Because the two styles were on different pages it makes inheriting from the default style impossible so what I did was build an App.xaml resource file with my style in it and then on both pages add the code:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resource.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
to my xaml. This meant that my page was then able to override the inherited style by using Mike Eason's code:
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">

Related

Complementing Application.Resources.Style with UserControl.Style for DataRow in DataGrid

I have a global style used in all the applications DataGrid's, defined in the Application.Resources:
<Application.Resources>
<ResourceDictionary>
<Style x:Key="StyleDataGridRow" TargetType="{x:Type DataGridRow}">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="DataGrid.IsSelected" Value="True">
<Setter Property="DataGrid.BorderBrush" Value="{DynamicResource SecondaryHueMidBrush}" />
<Setter Property="DataGrid.BorderThickness" Value="1" />
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" />
</Trigger>
<Trigger Property="DataGrid.IsSelected" Value="False">
<Setter Property="DataGrid.BorderBrush" Value="{DynamicResource SecondaryHueMidBrush}" />
<Setter Property="DataGrid.BorderThickness" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</Application:Resources>
In my UserControl I would like to add a style - keeping the global style - to highlight a row depending on an item used in this DataGrid. I could define this style in the UserControl's resources:
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="priceMissing" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=priceIsMissing}" Value="true">
<Setter Property="Background" Value="LightSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
The global style is applied to the UserControl's DataGrid like this:
<DataGrid x:Name="dgCalculatedServices"
Margin="20,0,0,0"
CellStyle="{StaticResource StyleDataGridCell}"
DataContext="{Binding}"
ItemsSource="{Binding calculationServiceCodes.collection}"
Style="{StaticResource StyleDataGrid}"
RowStyle="{StaticResource StyleDataGridRow}">
Does anyone know a way to use the global style on a DataGrid and complement it with the local style?
That is what the BasedOn property is for.
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 StyleDataGridRow style as the base style for priceMissing.
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="priceMissing" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource StyleDataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=priceIsMissing}" Value="true">
<Setter Property="Background" Value="LightSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
Then use the priceMissing style in your DataGrid.
<DataGrid x:Name="dgCalculatedServices
...
RowStyle="{StaticResource priceMissing}">
You could of course rename the priceMissing style to StyleDataGridRow instead. The style would then be overwritten in the scope of the UserControl.

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>

Applying styles dynamically for the TreeViewItems inside usercontrol in WPF

I want to apply styles to all RadTreeViewItems in usercontrol from my MainWindow.xaml. I have style related to RadTreeViewItem in resource dictionary and when I try to apply it to usercontrol it is throwing exception.
TreeItemStyle
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
>
<Style x:Key="GenericTreeItemStyle" TargetType="{x:Type telerik:RadTreeViewItem}" BasedOn="{StaticResource {x:Type telerik:RadTreeViewItem}}" >
<Setter Property="IsSelected" Value="{Binding IsSelected,Mode=TwoWay}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded,Mode=TwoWay}" />
<Setter Property="IsInEditMode" Value="{Binding IsInEditMode,Mode=TwoWay}" />
<Setter Property="FontWeight" Value="{Binding NodeFontLook,Mode=OneWay}"/>
<Setter Property="FontStyle" Value="{Binding NodeFontStyle,Mode=OneWay}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Usage in MainWindow.xaml
<UC:TreeUserControl Name="RepositoryTree" Style="{StaticResource GenericTreeItemStyle}"/>
It is giving exception
"'RadTreeViewItem' TargetType does not match type of element 'TreeUserControl'."
How to apply styles to inner controls of UserControl from MainWindow.xaml?

XAML partial styling?

I have these controls:
<Border Style="{StaticResource Button}">
<TextBlock>NEW</TextBlock>
</Border>
<Border Style="{StaticResource Button}">
<TextBlock>CLOSE</TextBlock>
</Border>
<Border Style="{StaticResource Button}">
<TextBlock>EXIT</TextBlock>
</Border>
And this style:
<Style x:Key="Button" TargetType="{x:Type Border}">
<Setter Property="Padding" Value="15, 10" />
<Setter Property="Margin" Value="5, 0" />
<Setter Property="MinWidth" Value="150" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
And I want to set each button/border to a specific, different color each, and another color for IsMouseOver.
I tried setting the Background on the control, but then the style can't overwrite the background and I can't do the IsMouseOver change.
I can only think of creating a different style for each one with their colors, but is there anyway to do a partial styling, like how you'd do in CSS?
<div class="button blue">NEW</div>
<div class="button red">CLOSE</div>
<div class="button gray">EXIT</div>
Or any other way to achieve this?
I haven't done any XAML in a while, so I'm a tad rusty. I'm pretty sure you can't do partial styles, but I know you can inherit styles using "BasedOn".
https://msdn.microsoft.com/en-us/library/system.windows.style.basedon(v=vs.110).aspx
This will allow you to do your base button style, and then create a color variant for each color you need based upon the common style features.
<Style x:Key="Button" TargetType="{x:Type Border}">
<Setter Property="Padding" Value="15, 10" />
<Setter Property="Margin" Value="5, 0" />
<Setter Property="MinWidth" Value="150" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
<Style x:Key="ButtonBlue" TargetType="{x:Type Border}" BasedOn="{StaticResource Button}">
<Setter Property="Background" Value="Blue" />
</Style>
Something like that, and then you use "ButtonBlue" instead of "Button" as the static resource you're referencing in the XAML for the control that you want to be blue. You should be able to add triggers as well in the inheriting style. Hopefully I'm remembering my syntax correctly.
Also, you may want to change the style Key to something other than "Button". Could be a bit confusing.

Categories