WPF: Moving panel resources to dictionary file - wpf

One of my Grid currently starts with the following code:
<Grid x:Name="Top_GRID" Margin="4.953,10" Width="817.28">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
<Style TargetType="Button">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
</Grid.Resources>
Just to clarify - I want to declare a Grid in which all TextBlocks are having the Background property set to "Red". All Button margins are set to "3" and so on.
I'd like to move the resource definition to a dictionary file.
Should I somehow wrap it as a Style?
If so, I'm going to have a recursive style declaration which (I think is illegal).
Sounds simple but I can't find the way to do it.

Try this
<Style x:Key="Grid_ControlStyle" TargetType="Grid">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
<Style TargetType="Button">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="3"/>
</Style>
</Style.Resources>
</Style>

You Need to put all styles for button, TextBox etc. in resourceDictionary file. Then add this file in application resources:
<Application x:Class="Aplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources\YourResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Then in xaml you will be able to use it like this
<TextBlock Grid.Column="1" Grid.Row="1" Text="bla bla" Style="{DynamicResource YourStyle}"/>
Finally your style should look like
<Style x:Key="StyleName" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="3,3,3,3"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="12pt"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
Hope thats what you was looking for.

Please go through the concept of resource dictionary in WPF. Any style, colors, fonts etc whatever is related to look of the application which you wish to be repeated in more than one screen of your application shpuld be placed in the resource dictionary.
x:Key is the property which can be used to access the style anywhere across the application.
For your resource dictionary to be accessible througout the application, place in it app.xaml

Related

How do I apply styles to different `TextBlock` objects?

Here is my Application ResourceDictionary
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CABI_PO_Manager.Themes">
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="YellowTextBlock">
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="#d8b243"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="GreenTextBlock">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="RedTextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#a01e21"/>
</Style>
</ResourceDictionary>
I want to have some default styles for a TextBlock which works
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
I found somewhere to use x:Key but I can't get it to work.
I will have several TextBlock's, How do I identify a TextBlock in the UI XAML as Red, Yellow or Green TextBlock and apply that style to them? This isn't recognized x:Key="GreenTextBlock"
<TextBlock x:Key="GreenTextBlock" Grid.Column="1" Margin="0,10,0,0" TextWrapping="Wrap" Text="PO Manager" VerticalAlignment="Top" TextAlignment="Center" FontWeight="ExtraBold"/>
If u want apply style on for example all TextBlocks in application, just use style without x:key defined e.g
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
When you are applying a style, use TargetType="{x:Type TextBlock}" instead of TargetType="TextBlock"
When do you use want to base on other style use
BasedOn="{StaticResource StyleUWantToBaseOn}"
where StyleUWantToBaseOn is style with x:Key property
And when you want to apply a specific style on lets say textblock you want to use Style property e.g:
<TextBlock Style="{StaticResource GreenTextBlock}" Grid.Column="1" />

Telerik Custom Style not reflecting when applied to RadButton

we are using telerik control in our WPF application. I am applying custom style for telerik control but it is not working.
<Style x:Key="RadButtonStyle" TargetType="telerik:RadButton">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Width" Value="60"/>
<Setter Property="Height" Value="22"/>
<Setter Property="Margin" Value="3,3,5,3"/>
</Style>
<telerik:RadButton Style="{StaticResource RadButtonStyle}"
Content="Login"
Margin="5"
cmd:Click.Command="
{Binding LoginCommand}" />
but style is not getting applied. it is actually hiding the button...
What I did: I have downloaded NugetPackage for Telerik Theme and added reference
<ResourceDictionary Source="/Telerik.Windows.Themes.Office_Black;component/Themes/System.Windows.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Office_Black;component/Themes/Telerik.Windows.Controls.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Office_Black;component/Themes/Telerik.Windows.Controls.Input.xaml"/>
<ResourceDictionary Source="/Telerik.Windows.Themes.Office_Black;component/Themes/Telerik.Windows.Controls.GridView.xaml"/>
Try to base your Style on the implicit one using the BasedOn property:
<Style x:Key="RadButtonStyle" TargetType="telerik:RadButton"
BasedOn="{StaticResource {x:Type telerik:RadButton}}">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Width" Value="60"/>
<Setter Property="Height" Value="22"/>
<Setter Property="Margin" Value="3,3,5,3"/>
</Style>

Code reusability in Styles

I have a style element which has minor edits and mostly repeated. How do i make it more generic - so setter properties are set within based on value versus repeating the code twice
<ResourceDictionary>
<Style x:Key="TextBlockStyleEnvironment" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="5,4,0,0" />
<Setter Property="FontSize" Value="8" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style x:Key="TextBlockStyleLocation" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="5,4,0,0" />
<Setter Property="FontSize" Value="10" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ResourceDictionary>
As you see from the code all setter properties are same except Margin and FontSize. Also attached is the screenshot of it on rendering.
Please note - want to keep this self contained within a Style and not have declare at local level in XAML when this being consumed.
Possible values of Env can be Dev,QA,Prod and possible values of location can be TK, LN
Consuming in XAML snippet as follows:
<Grid DataContext="{....}">
<StackPanel>
<TextBlock Text="{Binding Environment}" Style="{StaticResource TextBlockStyleEnvironment}"/>
<TextBlock Text="{Binding Location}" Style="{StaticResource TextBlockStyleLocation}"/>
You can use style inheritance:
<ResourceDictionary>
<Style x:Key="BaseTextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="5,4,0,0" />
<Setter Property="FontSize" Value="8" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style x:Key="TextBlockStyleEnvironment" BasedOn="{StaticResource BaseTextBlockStyle}" TargetType="{x:Type TextBlock}" />
<Style x:Key="TextBlockStyleLocation" BasedOn="{StaticResource BaseTextBlockStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="10" />
</Style>
</ResourceDictionary>
Additionally you can create attached properties and bind to those from within your control templates. This gives you the flexibility of not having to create hundreds of styles just because something minute needs to be different.
A good example of that is a button that has an image. When the mouse is over the image, the image needs to change. Typically you'd have to create a new control template/style for each button that implements that behavior. However, if you create two attached properties - NormalStateImageSource and MosueOverImageSource, you can bind to those in your control template. This allows you to have a single full blown style for the button, and later to declare individual styles for other buttons that only change the values of these attached properties.
There are few techniques in WPF world.
First, if styles are same type, it's possible to use BasedOn attribute:
<Style x:Key="GenericTextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="5,4,0,0" />
<Setter Property="FontSize" Value="8" />
</Style>
<Style x:Key="TextBlockStyleEnvironment"
BasedOn="{StaticResource GenericTextBlockStyle}"
TargetType="{x:Type TextBlock}">
</Style>
However the BasedOn attribute can get really messy sometimes. It's also possible to do it this way, which will work for elements that are not the same type:
<Thickness x:Key="LeftBorderMargin" Top="10" />
<Style x:Key="TextBlockStyleEnvironment" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="{StaticResource LeftBorderMargin}" />
</Style>
It's common practice to refactor all the colors / margins out from the Style element, for reusability.

Automatic Style Inheritance

I have a question about automatic style inheritance.
Basically, I have a superclass for which I would like to define the default style for textboxes and textblocks for classes that derive from it. These styles are based on my default styles as defined in Styles.xaml.
<controls:BaseUserControl.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DisplayLabel}">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Margin" Value="10,0,10,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource InputField}">
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="10,0,0,0"></Setter>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
</Style>
</controls:BaseUserControl.Resources>
This class is called DataEntryView.
Now when I derive from this class, the textblock and textboxes just get their default Windows look, not what I defined here.
<views:DataEntryView.Resources>
<!-- Do I need to add anything here? -->
</views:DataEntryView.Resources>
What is it that I'm forgetting?
Basically, I don't want to explicitly set the Style of every textblock and textbox to some key.
You need to place the styles in a RessourceDictionary and include this into the super class and the derived classes using the RessourceDictionary.MergedDictionaries property.
Styles file (Styles.xaml)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ....>
<Style ...> <!--Your styles goes here-->
</ResourceDictionary>
Controls (Parent and children):
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>

Default Image Style

It was my understanding that this:
<Style TargetType="{x:Type Image}">
<Setter Property="Margin" Value="0"/>
<Setter Property="Stretch" Value="None"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Cursor" Value="Help"/>
</Style>
would change the default image settings for each image rendered on the Window. Is this not the case? Is there an exception for images as it appears to work with other controls?
TIA
To set a style for a type you actually need to set the x:Key attribute like so:
<Style x:Key="{x:Type Image}" TargetType="{x:Type Image}">
<!-- setters here -->
</Style>

Resources