I have several image styles in my resource dictionary. As you can see, the alignment properties are duplicated so I'd like to bring these out to another style so their values are not duplicated. Is there a way to use linked styles in resource dictionary? and how can I do this?
<Style TargetType="Image" x:Key="Blank">
<Setter Property="Source" Value="/images/blank.png"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style TargetType="Image" x:Key="BlockArrowLeft">
<Setter Property="Source" Value="/images/block_arrow_left.png"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
Of course. You can use inheritance in styles:
<Style TargetType="Image" x:Key="common">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style TargetType="Image" x:Key="Blank" BasedOn="{StaticResource common}">
<Setter Property="Source" Value="/images/blank.png"/>
</Style>
<Style TargetType="Image" x:Key="BlockArrowLeft" BasedOn="{StaticResource common}">
<Setter Property="Source" Value="/images/block_arrow_left.png"/>
</Style>
Or:
<Style TargetType="Image">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style TargetType="Image" x:Key="Blank" BasedOn="{StaticResource {x:Type Image}}">
<Setter Property="Source" Value="/images/blank.png"/>
</Style>
<Style TargetType="Image" x:Key="BlockArrowLeft" BasedOn="{StaticResource {x:Type Image}}">
<Setter Property="Source" Value="/images/block_arrow_left.png"/>
</Style>
Related
Inside of app.xaml I have datagrid style
and for each window that contains a datagrid, I added an event setter for the datagridrow.
however, when I run it, I can see the style, but when I try to trigger the event nothing happens. if I remove the style from app.xaml. the event works well.
why app.xaml style disable my eventsetter?
here's the datagrid inside the app.xaml:
<Style TargetType="DataGrid">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="GridLinesVisibility" Value="None"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="RowStyle">
<Setter.Value>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ColumnHeaderStyle">
<Setter.Value>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Margin" Value="5,0,0,0"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{ x:Type DataGridColumnHeader}">
<Border BorderThickness="2,2,2,0" CornerRadius="5,5,0,0">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="White"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}" Value="{x:Null}">
<Setter Property="BorderBrush" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter HorizontalAlignment="Center" Margin="5"></ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
here's the eventsetter inside each window that contains datagrid:
<Style TargetType="DataGridRow">
<EventSetter Event="MouseDoubleClick" Handler="EditItem"/>
</Style>
It seems, that the grid uses the RowStyle from it's property later, than it has been set in window's resources. It will work, if you clear your RowStyle property in grid. Put this to the window's resources:
<Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="RowStyle" Value="{x:Null}"/>
</Style>
For you can use the style set in app.xaml, you have to move the RowStyle from property to global(in app.xaml):
<Style TargetType="DataGrid">
....
<Setter Property="RowStyle" Value="{x:Null}"/>
...
</Style>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="Background" Value="Green"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="Foreground" Value="White"/>
</Style>
and in window's resources:
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<EventSetter Event="MouseDoubleClick" Handler="PreviewMouseDown"/>
</Style>
I'm wondering how could I set my DataGrid Header Font size programatically, in case I would like to keep my font size in the database, because sometimes user might move aplication to a smaller monitor(1024x768) let's say and that simply he might edit his font size and everything is gonna be fine.
This is Style I am using right now to style my header:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#0091EA"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="40"/>
</Style>
So how could I set this properties from code behind if I would like to
Could I do simply smth like this:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#0091EA"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="{Binding FontSize}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="40"/>
</Style>
I changed <Setter Property="FontSize" Value="16"/>
to
<Setter Property="FontSize" Value="{Binding FontSize}"/>
Value="{Binding FontSize}" //is new
so how can I add value to this FontSize to be something from my code behind?
You could for example add a double property to your window:
public partial class MainWindow : Window
{
public double MyFontSize { get; set; } = 30;
public MainWindow()
{
InitializeComponent();
}
}
<Window.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#0091EA"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="{Binding MyFontSize, RelativeSource={RelativeSource AncestorType=Window}}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="40"/>
</Style
</Window.Resources>
Note that if you want to be able to change the value of the source property dynamically at runtime, the window class (or wherever you choose to implement the property) should implement the INotifyPropertyChanged event and raise change notifications.
I'm working on a program with multiple UserControls that should follow the same visual guidelines, as they will function as TabPages of an application to show some data to the user.
Basically, all of the UserControls have two columns. In column #1 I have a label describing which value belongs into the actual control and in the second column follows the control (TextBox, DatePicker, Checkbox etc.) for the user to set:
When I designed the first of those UserControls I ended up with a bunch of Styles that I set in the UserControls resources like this, so all Labels would have the same width, right-aligned text and vice versa:
<UserControl.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</UserControl.Resources>
Now, as I'm about to create all other 60+ UserControls I would like to avoid to add this exact same code over and over again to every single UserControl, just to achieve a consistency in visual style, like same fixed width for labels and so on, as this would be just horrible to maintain (imagine the customer requires all labels just to be 50px less wide...).
Is was wondering if there is any way of setting this formatting stuff once somewhere in the application and then just "import" those settings for my UserControls like this:
Master-file
<Master.Template1>
<Style TargetType="{x:Type Label}">
...
</Style>
<Style TargetType="{x:Type TextBox}">
...
</Style>
<Style TargetType="{x:Type ComboBox}">
...
</Style>
<Style TargetType="{x:Type DockPanel}">
...
</Style>
</Master.Template1>
Other UCs
<UserControl.Resources>
<using Style:Master.Template1/>
</UserControl.Resources>
I already read some stuff about this Application.ResourceDictionary, but I'm not sure if I'm on the right track with that, as I would prefer not to mess around with the code-behind files.
Or should I create my own Control that derives from a UserControl that already has all those values set in it's resources?
Add a new ResourceDictionary file to the project. Put your styles in the ResourceDictionary.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</ResourceDictionary>
Then add the resource dictionary to your UserControl.Resources
<UserControl.Resources>
<ResourceDictionary Source="MyResources.xaml"/>
</UserControl.Resources>
Edit:
Glen Thomas and myself managed to answer the question at the same time. I still leave my own answer up, as the article on MSDN contains some useful further information and upcoming users might find it useful to know how to add a ResourceDictionary in the first place.
Of course this is possible, and as easy as I hoped: ResourceDictionarys were the way to go!
This article in the MSDN poked me into the right direction.
I just added a new ResourceDictionary to my program
and put the reference code into it:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="250"/>
<Setter Property="DockPanel.Dock" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="DockPanel.Dock" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="DisplayMemberPath" Value="Value"/>
<Setter Property="SelectedValuePath" Value="Key"/>
<Setter Property="Margin" Value="2"/>
</Style>
<Style TargetType="{x:Type DockPanel}">
<Setter Property="DockPanel.Dock" Value="Top"/>
</Style>
</ResourceDictionary>
After that, I was able to "import" the Dictionary into my UserControl by replacing the UserControl.Resources with this:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ResourceDictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
And voilĂ : formatted controls with the ability to choose if to apply the resource "template" or not and a central place to modify the shared values.
Perfect!
I would like to nest Styles in WPF.
I have a resource dictionary:
<Style x:Key="BottomButtonBar" TargetType="{x:Type Grid}">
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
</Style>
What I want is: If I apply the style "BottomButtonBar" on a grid, Buttons which are inside this grid have Margin and Width I've defined and the same for the TextBlock inside this grid.
How to do that?
I finally found the following solution:
<Style x:Key="BottomButtonBar" TargetType="{x:Type Grid}">
<Style.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
</Style.Resources>
</Style>
And in the XAML:
<Grid DockPanel.Dock="Bottom" Style="{DynamicResource BottomButtonBar}">
If you want to add styles to elements in the Grid, you can make the styles implicit and add them to the resources of the Grid to limit their scope:
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10,2" />
<Setter Property="Width" Value="90" />
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0"/>
</Style>
<Grid.Resources />
<Button ... />
</Grid>
Is it possible to change a resource from another resource. I like to change the background of StartButtonRed if the mouse is over StartButtonMain.
<ImageBrush x:Key="RedBackgroundActive" ImageSource="/Images/start_red_active.png" Stretch="Fill"/>
<Style x:Key="StartButtonMain" TargetType="{x:Type local:SimpleButton}">
<Style.Resources>
<ImageBrush x:Key="MainBackground" ImageSource="/Images/start_main_normal.png" Stretch="Fill"/>
<ImageBrush x:Key="MainBackgroundActive" ImageSource="/Images/start_main_active.png" Stretch="Fill"/>
</Style.Resources>
<Style.Setters>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource MainBackground}"/>
<Setter Property="Visibility" Value="Visible"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource MainBackgroundActive}"/>
// Change the background of StartButtonRed to RedBackgroundActive
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="StartButtonRed" TargetType="{x:Type local:SimpleButton}">
<Style.Resources>
<ImageBrush x:Key="RedBackground" ImageSource="/Images/start_red_normal.png" Stretch="Fill"/>
</Style.Resources>
<Style.Setters>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Background" Value="{StaticResource RedBackground}"/>
<Setter Property="Visibility" Value="Visible"/>
</Style.Setters>
</Style>
You can't do this. Because styles are resources and triggers can only target FrameworkElements from within their own Template or using a Binding to an other actual FrameworkElement, you can't bind to another resource.
You could solve this with UserControl Triggers.